diff --git a/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts b/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts index a81e8cfff103..abe9df8c99d2 100644 --- a/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts @@ -572,6 +572,26 @@ Lorem Ipsum }); }); + it('parses markdown h1 title placed after export declarations', () => { + const markdown = dedent` + export function Author() { + return ( + Author + ); + } + + # Markdown Title + + Lorem Ipsum + + `; + + expect(parseMarkdownContentTitle(markdown)).toEqual({ + content: markdown, + contentTitle: 'Markdown Title', + }); + }); + it('parses markdown h1 title placed after multiple import declarations', () => { const markdown = dedent` import Component1 from '@site/src/components/Component1'; @@ -602,23 +622,21 @@ Lorem Ipsum }); }); - it('parses markdown h1 title placed after multiple import declarations and remove it', () => { + it('parses markdown h1 title placed after multiple import/export declarations and remove it', () => { const markdown = dedent` import Component1 from '@site/src/components/Component1'; import Component2 from '@site/src/components/Component2'; - import Component3 from '@site/src/components/Component3'; - import Component4 from '@site/src/components/Component4'; + export function Component3() { + return Component3 + } + + export function Component4() { + return Component4 + } import Component5 from '@site/src/components/Component5'; - import Component6 from '@site/src/components/Component6'; - import Component7 from '@site/src/components/Component7'; - import Component8 from '@site/src/components/Component8'; - import Component9 from '@site/src/components/Component9'; - import Component10 from '@site/src/components/Component10'; - import Component11 from '@site/src/components/Component11'; - import Component12 from '@site/src/components/Component12'; - import Component13 from '@site/src/components/Component13'; - import Component14 from '@site/src/components/Component14'; - import Component15 from '@site/src/components/Component15'; + export function Component6() { + return Component6 + } # Markdown Title @@ -633,6 +651,33 @@ Lorem Ipsum contentTitle: 'Markdown Title', }); }); + + it('parses markdown h1 title placed after multiple import/export declarations', () => { + const markdown = dedent` + import Component1 from '@site/src/components/Component1'; + import Component2 from '@site/src/components/Component2'; + export function Component3() { + return Component3 + } + + export function Component4() { + return Component4 + } + import Component5 from '@site/src/components/Component5'; + export function Component6() { + return Component6 + } + + # Markdown Title + + Lorem Ipsum + `; + + expect(parseMarkdownContentTitle(markdown)).toEqual({ + content: markdown, + contentTitle: 'Markdown Title', + }); + }); }); describe('parseFileContentFrontMatter', () => { diff --git a/packages/docusaurus-utils/src/markdownUtils.ts b/packages/docusaurus-utils/src/markdownUtils.ts index 216d0122e7ad..451ea7b22ff5 100644 --- a/packages/docusaurus-utils/src/markdownUtils.ts +++ b/packages/docusaurus-utils/src/markdownUtils.ts @@ -255,18 +255,18 @@ export function parseMarkdownContentTitle( const removeContentTitleOption = options?.removeContentTitle ?? false; const content = contentUntrimmed.trim(); - // We only need to detect import statements that will be parsed by MDX as - // `import` nodes, as broken syntax can't render anyways. That means any block - // that has `import` at the very beginning and surrounded by empty lines. - const contentWithoutImport = content - .replace(/^(?:import\s(?:.|\r?\n(?!\r?\n))*(?:\r?\n){2,})*/, '') + // We only need to detect import/export statements that will be parsed by MDX as + // `import` or `export` nodes, as broken syntax can't render anyways. That means any block + // that has `import` or `export` at the very beginning and surrounded by empty lines. + const contentWithoutImportExport = content + .replace(/^(?:(?:import|export)\s(?:.|\r?\n(?!\r?\n))*(?:\r?\n){2,})*/, '') .trim(); const regularTitleMatch = /^#[ \t]+(?[^ \t].*)(?:\r?\n|$)/.exec( - contentWithoutImport, + contentWithoutImportExport, ); const alternateTitleMatch = /^(?<title>.*)\r?\n=+(?:\r?\n|$)/.exec( - contentWithoutImport, + contentWithoutImportExport, ); const titleMatch = regularTitleMatch ?? alternateTitleMatch;