From ad6be47f6d58e72a9d3c6d875ad50db1cd42d791 Mon Sep 17 00:00:00 2001 From: Rafael Mestre Date: Wed, 30 Aug 2023 20:35:27 -0400 Subject: [PATCH 1/3] feat(content): support prismjs diff highlight --- .../docs-app/docs/features/routing/content.md | 23 ++++++++++++++ .../markdown-content-renderer.service.spec.ts | 17 ++++++++++ .../content/src/lib/marked-setup.service.ts | 31 ++++++++++--------- 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/apps/docs-app/docs/features/routing/content.md b/apps/docs-app/docs/features/routing/content.md index 489a552e9..3661d21fc 100644 --- a/apps/docs-app/docs/features/routing/content.md +++ b/apps/docs-app/docs/features/routing/content.md @@ -44,6 +44,29 @@ Analog is a meta-framework for Angular. [Back Home](./) ``` +### Using the diff highlight plugin + +Analog supports highlighting diff changes via PrismJS. 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..f9825abbc 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,21 @@ describe('MarkdownContentRendererService', () => { '
'
     );
   });
+
+  it('render should correctly highlight diff code blocks', async () => {
+    const { service } = setup();
+    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..fdc530553 100644
--- a/packages/content/src/lib/marked-setup.service.ts
+++ b/packages/content/src/lib/marked-setup.service.ts
@@ -11,11 +11,13 @@ import 'prismjs';
 import 'prismjs/plugins/toolbar/prism-toolbar';
 import 'prismjs/components/prism-bash';
 import 'prismjs/components/prism-css';
+import 'prismjs/components/prism-diff';
 import 'prismjs/components/prism-javascript';
 import 'prismjs/components/prism-json';
 import 'prismjs/components/prism-markup';
 import 'prismjs/components/prism-typescript';
 import 'prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard';
+import 'prismjs/plugins/diff-highlight/prism-diff-highlight';
 
 declare const Prism: typeof import('prismjs');
 
@@ -25,7 +27,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,24 +37,21 @@ export class MarkedSetupService {
       if (!lang) {
         return '
' + code + '
'; } - const langClass = 'language-' + lang; - const html = - '
' +
-        code +
-        '
'; - return html; + + const classes = lang.startsWith('diff') + ? `language-${lang} diff-highlight` + : `language-${lang}`; + return `
${code}
`; }; marked.use( gfmHeadingId(), markedHighlight({ async: true, - highlight: (code, lang) => { - lang = lang || 'typescript'; + highlight: (code: string, lang: string) => { + const diff = lang?.startsWith('diff-'); + lang = diff ? lang.replace('diff-', '') : lang || 'typescript'; + if (!Prism.languages[lang]) { if (lang !== 'mermaid') { console.warn(`Notice: @@ -65,7 +64,11 @@ export class MarkedSetupService { } return code; } - return Prism.highlight(code, Prism.languages[lang], lang); + return Prism.highlight( + code, + diff ? Prism.languages['diff'] : Prism.languages[lang], + lang + ); }, }), { From 7316d013556e6eedefdab542e9a2610f96ca09e1 Mon Sep 17 00:00:00 2001 From: Rafael Mestre Date: Thu, 31 Aug 2023 08:43:58 -0400 Subject: [PATCH 2/3] chore(content): removed additional imports and added docs on how to use them; improved some text --- .../docs-app/docs/features/routing/content.md | 12 +++++++++-- .../content/src/lib/marked-setup.service.ts | 21 +++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/apps/docs-app/docs/features/routing/content.md b/apps/docs-app/docs/features/routing/content.md index 3661d21fc..692aead25 100644 --- a/apps/docs-app/docs/features/routing/content.md +++ b/apps/docs-app/docs/features/routing/content.md @@ -44,9 +44,17 @@ Analog is a meta-framework for Angular. [Back Home](./) ``` -### Using the diff highlight plugin +### Using the diff Highlight Plugin -Analog supports highlighting diff changes via PrismJS. Use the `diff` language tag to highlight them or +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 --git a/packages/content/src/lib/marked-setup.service.ts b/packages/content/src/lib/marked-setup.service.ts index fdc530553..73b7eb30a 100644 --- a/packages/content/src/lib/marked-setup.service.ts +++ b/packages/content/src/lib/marked-setup.service.ts @@ -11,13 +11,11 @@ import 'prismjs'; import 'prismjs/plugins/toolbar/prism-toolbar'; import 'prismjs/components/prism-bash'; import 'prismjs/components/prism-css'; -import 'prismjs/components/prism-diff'; import 'prismjs/components/prism-javascript'; import 'prismjs/components/prism-json'; import 'prismjs/components/prism-markup'; import 'prismjs/components/prism-typescript'; import 'prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard'; -import 'prismjs/plugins/diff-highlight/prism-diff-highlight'; declare const Prism: typeof import('prismjs'); @@ -52,15 +50,26 @@ export class MarkedSetupService { const diff = lang?.startsWith('diff-'); lang = diff ? lang.replace('diff-', '') : lang || 'typescript'; + if (diff && !Prism.languages['diff']) { + 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; } From 36d8a3082b89456587030fcd85978901029d707e Mon Sep 17 00:00:00 2001 From: Rafael Mestre Date: Thu, 31 Aug 2023 09:17:22 -0400 Subject: [PATCH 3/3] chore(content): fall back to language-only highlight when diff plugin isn't imported; improve tests --- .../markdown-content-renderer.service.spec.ts | 19 +++++++++++++++++++ .../content/src/lib/marked-setup.service.ts | 10 ++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) 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 f9825abbc..fcc820a92 100644 --- a/packages/content/src/lib/markdown-content-renderer.service.spec.ts +++ b/packages/content/src/lib/markdown-content-renderer.service.spec.ts @@ -35,6 +35,7 @@ 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); @@ -49,4 +50,22 @@ describe('MarkdownContentRendererService', () => { '
'
     );
   });
+
+  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 73b7eb30a..2f82a7ad7 100644
--- a/packages/content/src/lib/marked-setup.service.ts
+++ b/packages/content/src/lib/marked-setup.service.ts
@@ -36,9 +36,10 @@ export class MarkedSetupService {
         return '
' + code + '
'; } - const classes = lang.startsWith('diff') - ? `language-${lang} diff-highlight` - : `language-${lang}`; + const classes = + lang.startsWith('diff') && Prism.languages['diff'] + ? `language-${lang} diff-highlight` + : `language-${lang.replace('diff-', '')}`; return `
${code}
`; }; @@ -47,10 +48,11 @@ export class MarkedSetupService { markedHighlight({ async: true, highlight: (code: string, lang: string) => { - const diff = lang?.startsWith('diff-'); + 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.