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.
This commit is contained in:
Alois Klink 2023-01-19 00:06:58 +00:00
parent 8f4caa4537
commit 2f1a521db6
2 changed files with 41 additions and 13 deletions

View File

@ -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

View File

@ -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');
});