From 2f1a521db65d7fe77bcf050c24469db43a573b3d Mon Sep 17 00:00:00 2001 From: Alois Klink Date: Thu, 19 Jan 2023 00:06:58 +0000 Subject: [PATCH] build(docs): add auto-generated header after YAML Add the auto-generated header after any YAML front-matter blocks. YAML front-matter is normally only valid in Markdown when it's at the beginning of the Markdown file. GitHub/Vitepress may otherwise render it incorrectly. --- packages/mermaid/src/docs.mts | 40 ++++++++++++++++++++++++------- packages/mermaid/src/docs.spec.ts | 14 +++++++---- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/packages/mermaid/src/docs.mts b/packages/mermaid/src/docs.mts index 4fe18001b..07f393df1 100644 --- a/packages/mermaid/src/docs.mts +++ b/packages/mermaid/src/docs.mts @@ -199,17 +199,32 @@ const transformIncludeStatements = (file: string, text: string): string => { }); }; +/** Options for {@link transformMarkdownAst} */ +interface TransformMarkdownAstOptions { + /** + * Used to indicate the original/source file. + */ + originalFilename: string; + /** If `true`, add a warning that the file is autogenerated */ + addAutogeneratedWarning?: boolean; +} + /** - * Remark plugin that transforms code blocks in a Markdown file. + * Remark plugin that transforms mermaid repo markdown to Vitepress/GFM markdown. * * For any AST node that is a code block: transform it as needed: * - blocks marked as MERMAID_DIAGRAM_ONLY will be set to a 'mermaid' code block so it will be rendered as (only) a diagram * - blocks marked as MERMAID_EXAMPLE_KEYWORDS will be copied and the original node will be a code only block and the copy with be rendered as the diagram * - blocks marked as BLOCK_QUOTE_KEYWORDS will be transformed into block quotes * + * If `addAutogeneratedWarning` is `true`, generates a header stating that this file is autogenerated. + * * @returns plugin function for Remark */ -export function transformMarkdownAst() { +export function transformMarkdownAst({ + originalFilename, + addAutogeneratedWarning, +}: TransformMarkdownAstOptions) { return (tree: Root, _file?: any): Root => { const astWithTransformedBlocks = flatmap(tree, (node: Code) => { if (node.type !== 'code' || !node.lang) { @@ -236,6 +251,17 @@ export function transformMarkdownAst() { return [node]; // default is to do nothing to the node }); + if (addAutogeneratedWarning) { + // Add the header to the start of the file + const headerNode = remark.parse(generateHeader(originalFilename)).children[0]; + if (astWithTransformedBlocks.children[0].type === 'yaml') { + // insert header after the YAML frontmatter if it exists + astWithTransformedBlocks.children.splice(1, 0, headerNode); + } else { + astWithTransformedBlocks.children.unshift(headerNode); + } + } + return astWithTransformedBlocks; }; } @@ -260,13 +286,9 @@ const transformMarkdown = (file: string) => { let transformed = remark() .use(remarkGfm) .use(remarkFrontmatter, ['yaml']) // support YAML front-matter in Markdown - .use(transformMarkdownAst) // mermaid project specific plugin - .processSync(doc).toString(); - - if (!noHeader) { - // Add the header to the start of the file - transformed = `${generateHeader(file)}\n${transformed}`; - } + .use(transformMarkdownAst, { originalFilename: file, addAutogeneratedWarning: !noHeader }) // mermaid project specific plugin + .processSync(doc) + .toString(); if (vitepress && file === 'src/docs/index.md') { // Skip transforming index if vitepress is enabled diff --git a/packages/mermaid/src/docs.spec.ts b/packages/mermaid/src/docs.spec.ts index 5b47146d5..1ce708e93 100644 --- a/packages/mermaid/src/docs.spec.ts +++ b/packages/mermaid/src/docs.spec.ts @@ -7,13 +7,15 @@ afterEach(() => { vi.restoreAllMocks(); }); +const originalFilename = 'example-input-filename.md'; + describe('docs.mts', () => { describe('transformMarkdownAst', () => { describe('checks each AST node', () => { it('does no transformation if there are no code blocks', async () => { const contents = 'Markdown file contents\n'; const result = ( - await remarkBuilder().use(transformMarkdownAst).process(contents) + await remarkBuilder().use(transformMarkdownAst, { originalFilename }).process(contents) ).toString(); expect(result).toEqual(contents); }); @@ -28,7 +30,9 @@ describe('docs.mts', () => { it('changes the language to "mermaid"', async () => { const result = ( - await remarkBuilder().use(transformMarkdownAst).process(contents) + await remarkBuilder() + .use(transformMarkdownAst, { originalFilename }) + .process(contents) ).toString(); expect(result).toEqual( beforeCodeLine + '\n' + '```' + 'mermaid' + '\n' + diagram_text + '\n```\n' @@ -45,7 +49,9 @@ describe('docs.mts', () => { it('changes the language to "mermaid-example" and adds a copy of the code block with language = "mermaid"', async () => { const result = ( - await remarkBuilder().use(transformMarkdownAst).process(contents) + await remarkBuilder() + .use(transformMarkdownAst, { originalFilename }) + .process(contents) ).toString(); expect(result).toEqual( beforeCodeLine + @@ -67,7 +73,7 @@ describe('docs.mts', () => { beforeCodeLine + '```' + lang_keyword + '\n' + 'This is the text\n' + '```\n'; const result = ( - await remarkBuilder().use(transformMarkdownAst).process(contents) + await remarkBuilder().use(transformMarkdownAst, { originalFilename }).process(contents) ).toString(); expect(result).toEqual(beforeCodeLine + '\n> **Note**\n' + '> This is the text\n'); });