From bfc8debf654dace272b8cc90b905a5581f8242a8 Mon Sep 17 00:00:00 2001 From: Vishal Sharma Date: Tue, 10 Nov 2026 19:32:27 +0530 Subject: [PATCH 1/2] fix(utils): preserve trailing hash in ATX heading titles --- .../src/__tests__/markdownUtils.test.ts | 42 +++++++++++++++++++ .../docusaurus-utils/src/markdownUtils.ts | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts b/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts index 34648991ba35..e6ec8f9d7641 100644 --- a/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts @@ -438,6 +438,48 @@ Lorem Ipsum }); }); + it('parses markdown h1 title preserving trailing hash in word (e.g. C#)', () => { + const markdown = dedent` + + # Learn C# + + Lorem Ipsum + + `; + expect(parseMarkdownContentTitle(markdown)).toEqual({ + content: markdown, + contentTitle: 'Learn C#', + }); + }); + + it('parses markdown h1 title preserving trailing hash in word with closing #', () => { + const markdown = dedent` + + # Learn C# # + + Lorem Ipsum + + `; + expect(parseMarkdownContentTitle(markdown)).toEqual({ + content: markdown, + contentTitle: 'Learn C#', + }); + }); + + it('parses markdown h1 title preserving trailing hash in word with anchor id', () => { + const markdown = dedent` + + # Learn C# {#learn-csharp} + + Lorem Ipsum + + `; + expect(parseMarkdownContentTitle(markdown)).toEqual({ + content: markdown, + contentTitle: 'Learn C#', + }); + }); + it('parses markdown h1 title at the top followed by h2 title', () => { const markdown = dedent` diff --git a/packages/docusaurus-utils/src/markdownUtils.ts b/packages/docusaurus-utils/src/markdownUtils.ts index 3a82a52cbb6e..d2b519265cd2 100644 --- a/packages/docusaurus-utils/src/markdownUtils.ts +++ b/packages/docusaurus-utils/src/markdownUtils.ts @@ -334,7 +334,7 @@ export function parseMarkdownContentTitle( contentTitle: toTextContentTitle( regularTitleMatch .groups!.title!.trim() - .replace(/\s*(?:\{#*[\w-]+\}|#+)$/, ''), + .replace(/(?:\s*\{#*[\w-]+\}|\s+#+)$/, ''), ).trim(), }; } From 1ec580fd9614dd723af3365c42d62f02c844728c Mon Sep 17 00:00:00 2001 From: Vishal Sharma Date: Tue, 10 Nov 2026 19:51:33 +0530 Subject: [PATCH 2/2] fix(utils): handle headings consisting only of closing hashes --- .../src/__tests__/markdownUtils.test.ts | 14 ++++++++++++++ packages/docusaurus-utils/src/markdownUtils.ts | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts b/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts index e6ec8f9d7641..fef512de0e97 100644 --- a/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts @@ -480,6 +480,20 @@ Lorem Ipsum }); }); + it('parses markdown h1 title consisting only of closing hashes as empty', () => { + const markdown = dedent` + + # ### + + Lorem Ipsum + + `; + expect(parseMarkdownContentTitle(markdown)).toEqual({ + content: markdown, + contentTitle: '', + }); + }); + it('parses markdown h1 title at the top followed by h2 title', () => { const markdown = dedent` diff --git a/packages/docusaurus-utils/src/markdownUtils.ts b/packages/docusaurus-utils/src/markdownUtils.ts index d2b519265cd2..022079f5d757 100644 --- a/packages/docusaurus-utils/src/markdownUtils.ts +++ b/packages/docusaurus-utils/src/markdownUtils.ts @@ -334,7 +334,7 @@ export function parseMarkdownContentTitle( contentTitle: toTextContentTitle( regularTitleMatch .groups!.title!.trim() - .replace(/(?:\s*\{#*[\w-]+\}|\s+#+)$/, ''), + .replace(/(?:\s*\{#*[\w-]+\}|\s+#+|^#+)$/, ''), ).trim(), }; }