feat: support mermaid code blocks in Markdown (#7490)

Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
This commit is contained in:
Sam Wall 2022-10-14 17:07:20 +01:00 committed by GitHub
parent d2fdd981f7
commit 9c92a79d23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 1666 additions and 13 deletions

View file

@ -22,8 +22,10 @@ import toc from './remark/toc';
import unwrapMdxCodeBlocks from './remark/unwrapMdxCodeBlocks';
import transformImage from './remark/transformImage';
import transformLinks from './remark/transformLinks';
import mermaid from './remark/mermaid';
import transformAdmonitions from './remark/admonitions';
import type {MarkdownConfig} from '@docusaurus/types';
import type {LoaderContext} from 'webpack';
import type {Processor, Plugin} from 'unified';
import type {AdmonitionOptions} from './remark/admonitions';
@ -61,6 +63,7 @@ export type MDXOptions = {
};
export type Options = Partial<MDXOptions> & {
markdownConfig: MarkdownConfig;
staticDirs: string[];
siteDir: string;
isMDXPartial?: (filePath: string) => boolean;
@ -71,7 +74,6 @@ export type Options = Partial<MDXOptions> & {
frontMatter: {[key: string]: unknown};
metadata: {[key: string]: unknown};
}) => {[key: string]: unknown};
filepath: string;
};
/**
@ -171,6 +173,7 @@ export async function mdxLoader(
...(reqOptions.beforeDefaultRemarkPlugins ?? []),
...getAdmonitionsPlugins(reqOptions.admonitions ?? false),
...DEFAULT_OPTIONS.remarkPlugins,
...(reqOptions.markdownConfig.mermaid ? [mermaid] : []),
[
transformImage,
{

View file

@ -0,0 +1,51 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`mermaid remark plugin does nothing if there's no mermaid code block 1`] = `
"
const layoutProps = {
};
const MDXLayout = "wrapper"
export default function MDXContent({
components,
...props
}) {
return <MDXLayout {...layoutProps} {...props} components={components} mdxType="MDXLayout">
<h1>{\`Heading 1\`}</h1>
<p>{\`No Mermaid diagram :(\`}</p>
<pre><code parentName="pre" {...{
"className": "language-js"
}}>{\`this is not mermaid
\`}</code></pre>
</MDXLayout>;
}
;
MDXContent.isMDXComponent = true;"
`;
exports[`mermaid remark plugin works for basic mermaid code blocks 1`] = `
"
const layoutProps = {
};
const MDXLayout = "wrapper"
export default function MDXContent({
components,
...props
}) {
return <MDXLayout {...layoutProps} {...props} components={components} mdxType="MDXLayout">
<h1>{\`Heading 1\`}</h1>
<mermaid {...{
"value": "graph TD;/n A-->B;/n A-->C;/n B-->D;/n C-->D;"
}}></mermaid>
</MDXLayout>;
}
;
MDXContent.isMDXComponent = true;"
`;

View file

@ -0,0 +1,46 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {createCompiler} from '@mdx-js/mdx';
import mermaid from '..';
describe('mermaid remark plugin', () => {
function createTestCompiler() {
return createCompiler({
remarkPlugins: [mermaid],
});
}
it("does nothing if there's no mermaid code block", async () => {
const mdxCompiler = createTestCompiler();
const result = await mdxCompiler.process(
`# Heading 1
No Mermaid diagram :(
\`\`\`js
this is not mermaid
\`\`\`
`,
);
expect(result.contents).toMatchSnapshot();
});
it('works for basic mermaid code blocks', async () => {
const mdxCompiler = createTestCompiler();
const result = await mdxCompiler.process(`# Heading 1
\`\`\`mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
\`\`\``);
expect(result.contents).toMatchSnapshot();
});
});

View file

@ -0,0 +1,32 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import visit from 'unist-util-visit';
import type {Transformer} from 'unified';
import type {Code} from 'mdast';
// TODO: this plugin shouldn't be in the core MDX loader
// After we allow plugins to provide Remark/Rehype plugins (see
// https://github.com/facebook/docusaurus/issues/6370), this should be provided
// by theme-mermaid itself
export default function plugin(): Transformer {
return (root) => {
visit(root, 'code', (node: Code, index, parent) => {
if (node.lang === 'mermaid') {
parent!.children.splice(index, 1, {
type: 'mermaidCodeBlock',
data: {
hName: 'mermaid',
hProperties: {
value: node.value,
},
},
});
}
});
};
}