From 3176a2ccbab4b05fa110604fbcf3f0aadb04755b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E5=B0=8F=E5=A2=A8?= <16949192+coder-xiaomo@users.noreply.github.com> Date: Tue, 1 Apr 2025 21:14:02 +0800 Subject: [PATCH] fix(theme): Fix code block magic comments with CRLF line breaks bug (#11046) * fix: with CRLF line breaks, an extra empty line was rendered with // highlight-end at end of code blocks See: #11036 * Add unit tests --------- Co-authored-by: sebastien --- .../__snapshots__/codeBlockUtils.test.ts.snap | 24 +++++++++++++++++++ .../utils/__tests__/codeBlockUtils.test.ts | 23 ++++++++++++++++++ .../src/utils/codeBlockUtils.ts | 4 ++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-theme-common/src/utils/__tests__/__snapshots__/codeBlockUtils.test.ts.snap b/packages/docusaurus-theme-common/src/utils/__tests__/__snapshots__/codeBlockUtils.test.ts.snap index ca223444b4..9c3d5cb015 100644 --- a/packages/docusaurus-theme-common/src/utils/__tests__/__snapshots__/codeBlockUtils.test.ts.snap +++ b/packages/docusaurus-theme-common/src/utils/__tests__/__snapshots__/codeBlockUtils.test.ts.snap @@ -70,6 +70,30 @@ bbbbb", } `; +exports[`parseLines handles CRLF line breaks with highlight comments correctly 1`] = ` +{ + "code": "aaaaa +bbbbb", + "lineClassNames": { + "1": [ + "theme-code-block-highlighted-line", + ], + }, +} +`; + +exports[`parseLines handles CRLF line breaks with highlight metastring 1`] = ` +{ + "code": "aaaaa +bbbbb", + "lineClassNames": { + "1": [ + "theme-code-block-highlighted-line", + ], + }, +} +`; + exports[`parseLines handles one line with multiple class names 1`] = ` { "code": " diff --git a/packages/docusaurus-theme-common/src/utils/__tests__/codeBlockUtils.test.ts b/packages/docusaurus-theme-common/src/utils/__tests__/codeBlockUtils.test.ts index 91d2efe659..b3a47f00d7 100644 --- a/packages/docusaurus-theme-common/src/utils/__tests__/codeBlockUtils.test.ts +++ b/packages/docusaurus-theme-common/src/utils/__tests__/codeBlockUtils.test.ts @@ -360,6 +360,29 @@ line ), ).toMatchSnapshot(); }); + + it('handles CRLF line breaks with highlight comments correctly', () => { + expect( + parseLines( + `aaaaa\r\n// highlight-start\r\nbbbbb\r\n// highlight-end\r\n`, + { + metastring: '', + language: 'js', + magicComments: defaultMagicComments, + }, + ), + ).toMatchSnapshot(); + }); + + it('handles CRLF line breaks with highlight metastring', () => { + expect( + parseLines(`aaaaa\r\nbbbbb\r\n`, { + metastring: '{2}', + language: 'js', + magicComments: defaultMagicComments, + }), + ).toMatchSnapshot(); + }); }); describe('getLineNumbersStart', () => { diff --git a/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts b/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts index 305ba3e877..548a5dc0ba 100644 --- a/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts @@ -241,7 +241,7 @@ export function parseLines( */ code: string; } { - let code = content.replace(/\n$/, ''); + let code = content.replace(/\r?\n$/, ''); const {language, magicComments, metastring} = options; // Highlighted lines specified in props: don't parse the content if (metastring && metastringLinesRangeRegex.test(metastring)) { @@ -266,7 +266,7 @@ export function parseLines( magicComments, ); // Go through line by line - const lines = code.split('\n'); + const lines = code.split(/\r?\n/); const blocks = Object.fromEntries( magicComments.map((d) => [d.className, {start: 0, range: ''}]), );