diff --git a/apps/docs-app/docs/features/routing/content.md b/apps/docs-app/docs/features/routing/content.md index 489a552e9..692aead25 100644 --- a/apps/docs-app/docs/features/routing/content.md +++ b/apps/docs-app/docs/features/routing/content.md @@ -44,6 +44,37 @@ Analog is a meta-framework for Angular. [Back Home](./) ``` +### Using the diff Highlight Plugin + +Analog supports highlighting diff changes with PrismJS. Add the `diff` +language and `diff-highlight` plugin imports to `app.config.ts`: + +```ts +import 'prismjs/components/prism-diff'; +import 'prismjs/plugins/diff-highlight/prism-diff-highlight'; +``` + +Use the `diff` language tag to highlight them or +`diff-` to highlight the diff changes in a specific language. + +````md +```diff +- This is a sentence. ++ This is a longer sentence. +``` + +```diff-typescript +- const foo = 'bar'; ++ const foo = 'baz'; +``` +```` + +To highlight changed line backgrounds instead of just the text, add this import to your global stylesheet: + +```css +@import 'prismjs/plugins/diff-highlight/prism-diff-highlight.css'; +``` + ## Defining Content Files For more flexibility, markdown content files can be provided in the `src/content` folder. Here you can list markdown files such as blog posts. diff --git a/packages/content/src/lib/markdown-content-renderer.service.spec.ts b/packages/content/src/lib/markdown-content-renderer.service.spec.ts index d957616ec..fcc820a92 100644 --- a/packages/content/src/lib/markdown-content-renderer.service.spec.ts +++ b/packages/content/src/lib/markdown-content-renderer.service.spec.ts @@ -32,4 +32,40 @@ describe('MarkdownContentRendererService', () => { '
'
     );
   });
+
+  it('render should correctly highlight diff code blocks', async () => {
+    const { service } = setup();
+    window.Prism.languages['diff'] = {};
+    let testCode = "```diff-javascript\nconsole.log('Hello, world!');\n```";
+    let result = await service.render(testCode);
+
+    expect(result).toContain(
+      '
'
+    );
+
+    testCode = "```diff-typescript\nconsole.log('Hello, world!');\n```";
+    result = await service.render(testCode);
+
+    expect(result).toContain(
+      '
'
+    );
+  });
+
+  it('render should fall back to language-only highlighting if `diff` plugin is not imported', async () => {
+    const { service } = setup();
+    window.Prism.languages['diff'] = undefined;
+    let testCode = "```diff-javascript\nconsole.log('Hello, world!');\n```";
+    let result = await service.render(testCode);
+
+    expect(result).toContain(
+      '
'
+    );
+
+    testCode = "```diff-typescript\nconsole.log('Hello, world!');\n```";
+    result = await service.render(testCode);
+
+    expect(result).toContain(
+      '
'
+    );
+  });
 });
diff --git a/packages/content/src/lib/marked-setup.service.ts b/packages/content/src/lib/marked-setup.service.ts
index 61ad0c8e9..2f82a7ad7 100644
--- a/packages/content/src/lib/marked-setup.service.ts
+++ b/packages/content/src/lib/marked-setup.service.ts
@@ -25,7 +25,7 @@ export class MarkedSetupService {
 
   constructor() {
     const renderer = new marked.Renderer();
-    renderer.code = (code, lang) => {
+    renderer.code = (code: string, lang: string) => {
       // Let's do a language based detection like on GitHub
       // So we can still have non-interpreted mermaid code
       if (lang === 'mermaid') {
@@ -35,37 +35,51 @@ export class MarkedSetupService {
       if (!lang) {
         return '
' + code + '
'; } - const langClass = 'language-' + lang; - const html = - '
' +
-        code +
-        '
'; - return html; + + const classes = + lang.startsWith('diff') && Prism.languages['diff'] + ? `language-${lang} diff-highlight` + : `language-${lang.replace('diff-', '')}`; + return `
${code}
`; }; marked.use( gfmHeadingId(), markedHighlight({ async: true, - highlight: (code, lang) => { - lang = lang || 'typescript'; + highlight: (code: string, lang: string) => { + let diff = lang?.startsWith('diff-'); + lang = diff ? lang.replace('diff-', '') : lang || 'typescript'; + + if (diff && !Prism.languages['diff']) { + diff = false; + console.warn(`Notice: + --------------------------------------------------------------------------------------- + The \`diff\` language and plugin are not available in the provided setup. + To enable it, add the following imports your \`main.ts\`: + import 'prismjs/components/prism-diff'; + import 'prismjs/plugins/diff-highlight/prism-diff-highlight'; + --------------------------------------------------------------------------------------- + `); + } + if (!Prism.languages[lang]) { if (lang !== 'mermaid') { console.warn(`Notice: --------------------------------------------------------------------------------------- - The requested language '${lang}' is not available with the provided setup. - To enable, import your main.ts as: - import 'prismjs/components/prism-${lang}'; + The requested language '${lang}' is not available in the provided setup. + To enable it, add the following import your \`main.ts\`: + import 'prismjs/components/prism-${lang}'; --------------------------------------------------------------------------------------- - `); + `); } return code; } - return Prism.highlight(code, Prism.languages[lang], lang); + return Prism.highlight( + code, + diff ? Prism.languages['diff'] : Prism.languages[lang], + lang + ); }, }), {