Skip to content

Commit

Permalink
feat: support mermaid code blocks in Markdown (#7490)
Browse files Browse the repository at this point in the history
Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
# Conflicts:
#	project-words.txt
#	website/package.json
#	yarn.lock
  • Loading branch information
sjwall authored and slorber committed Oct 28, 2022
1 parent a990a5e commit 433f08b
Show file tree
Hide file tree
Showing 39 changed files with 4,812 additions and 2,939 deletions.
1 change: 1 addition & 0 deletions packages/docusaurus-mdx-loader/package.json
Expand Up @@ -40,6 +40,7 @@
"@docusaurus/types": "2.1.0",
"@types/escape-html": "^1.0.2",
"@types/mdast": "^3.0.10",
"@types/mermaid": "^8.2.9",
"@types/stringify-object": "^3.3.1",
"@types/unist": "^2.0.6",
"rehype-stringify": "^8.0.0",
Expand Down
5 changes: 4 additions & 1 deletion packages/docusaurus-mdx-loader/src/loader.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -61,6 +63,7 @@ export type MDXOptions = {
};

export type Options = Partial<MDXOptions> & {
markdownConfig: MarkdownConfig;
staticDirs: string[];
siteDir: string;
isMDXPartial?: (filePath: string) => boolean;
Expand All @@ -71,7 +74,6 @@ export type Options = Partial<MDXOptions> & {
frontMatter: {[key: string]: unknown};
metadata: {[key: string]: unknown};
}) => {[key: string]: unknown};
filepath: string;
};

/**
Expand Down Expand Up @@ -171,6 +173,7 @@ export async function mdxLoader(
...(reqOptions.beforeDefaultRemarkPlugins ?? []),
...getAdmonitionsPlugins(reqOptions.admonitions ?? false),
...DEFAULT_OPTIONS.remarkPlugins,
...(reqOptions.markdownConfig.mermaid ? [mermaid] : []),
[
transformImage,
{
Expand Down
@@ -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;"
`;
@@ -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();
});
});
32 changes: 32 additions & 0 deletions packages/docusaurus-mdx-loader/src/remark/mermaid/index.ts
@@ -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,
},
},
});
}
});
};
}
1 change: 1 addition & 0 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Expand Up @@ -455,6 +455,7 @@ export default async function pluginContentBlog(
(author) => author.imageURL,
),
}),
markdownConfig: siteConfig.markdown,
},
},
{
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus-plugin-content-docs/src/index.ts
Expand Up @@ -375,6 +375,7 @@ export default async function pluginContentDocs(
}) => ({
image: frontMatter.image,
}),
markdownConfig: siteConfig.markdown,
},
},
{
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus-plugin-content-pages/src/index.ts
Expand Up @@ -211,6 +211,7 @@ export default function pluginContentPages(
`${docuHash(aliasedSource)}.json`,
);
},
markdownConfig: siteConfig.markdown,
},
},
{
Expand Down
10 changes: 10 additions & 0 deletions packages/docusaurus-theme-classic/src/theme-classic.d.ts
Expand Up @@ -788,6 +788,7 @@ declare module '@theme/MDXComponents' {
import type MDXUl from '@theme/MDXComponents/Ul';
import type MDXImg from '@theme/MDXComponents/Img';
import type Admonition from '@theme/Admonition';
import type Mermaid from '@theme/Mermaid';

export type MDXComponentsObject = {
readonly head: typeof MDXHead;
Expand All @@ -804,6 +805,7 @@ declare module '@theme/MDXComponents' {
readonly h5: (props: ComponentProps<'h5'>) => JSX.Element;
readonly h6: (props: ComponentProps<'h6'>) => JSX.Element;
readonly admonition: typeof Admonition;
readonly mermaid: typeof Mermaid;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[tagName: string]: ComponentType<any>;
};
Expand Down Expand Up @@ -1112,6 +1114,14 @@ declare module '@theme/SearchBar' {
export default function SearchBar(): JSX.Element;
}

declare module '@theme/Mermaid' {
export interface Props {
value: string;
}

export default function Mermaid(props: Props): JSX.Element;
}

declare module '@theme/TabItem' {
import type {ReactNode} from 'react';

Expand Down
Expand Up @@ -15,6 +15,7 @@ import MDXHeading from '@theme/MDXComponents/Heading';
import MDXUl from '@theme/MDXComponents/Ul';
import MDXImg from '@theme/MDXComponents/Img';
import Admonition from '@theme/Admonition';
import Mermaid from '@theme/Mermaid';

import type {MDXComponentsObject} from '@theme/MDXComponents';

Expand All @@ -33,6 +34,7 @@ const MDXComponents: MDXComponentsObject = {
h5: (props) => <MDXHeading as="h5" {...props} />,
h6: (props) => <MDXHeading as="h6" {...props} />,
admonition: Admonition,
mermaid: Mermaid,
};

export default MDXComponents;
16 changes: 16 additions & 0 deletions packages/docusaurus-theme-classic/src/theme/Mermaid.tsx
@@ -0,0 +1,16 @@
/**
* 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.
*/

// This component is meant to be implemented by a Mermaid renderer theme
// It is notable created to be overridden by docusaurus-theme-mermaid

// By default, the classic theme does not provide any Mermaid implementation
// Yet we declare it there so that we can register it in MDX
// TODO later the mermaid theme should be able to register its MDX component
// see https://github.com/facebook/docusaurus/pull/7490#issuecomment-1279117288

export {default} from '@docusaurus/Noop';
3 changes: 3 additions & 0 deletions packages/docusaurus-theme-mermaid/.npmignore
@@ -0,0 +1,3 @@
.tsbuildinfo*
tsconfig*
__tests__
21 changes: 21 additions & 0 deletions packages/docusaurus-theme-mermaid/README.md
@@ -0,0 +1,21 @@
# Docusaurus Theme Mermaid

The mermaid components for Docusaurus.

## Installation

Add `docusaurus/theme-mermaid` to your package:

```bash
npm i @docusaurus/theme-mermaid
# or
yarn add @docusaurus/theme-mermaid
```

## Swizzling components

```bash
$ npm swizzle @docusaurus/theme-mermaid [component name]
```

All components used by this theme can be found [here](https://github.com/facebook/docusaurus/tree/main/packages/docusaurus-theme-mermaid/src/theme)
57 changes: 57 additions & 0 deletions packages/docusaurus-theme-mermaid/package.json
@@ -0,0 +1,57 @@
{
"name": "@docusaurus/theme-mermaid",
"version": "2.1.0",
"description": "Mermaid components for Docusaurus.",
"main": "lib/index.js",
"types": "src/theme-mermaid.d.ts",
"sideEffects": false,
"exports": {
"./lib/*": "./lib/*",
"./src/*": "./src/*",
"./client": {
"type": "./lib/client/index.d.ts",
"default": "./lib/client/index.js"
},
".": {
"types": "./src/theme-mermaid.d.ts",
"default": "./lib/index.js"
}
},
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/facebook/docusaurus.git",
"directory": "packages/docusaurus-theme-mermaid"
},
"license": "MIT",
"scripts": {
"build": "tsc --build && node ../../admin/scripts/copyUntypedFiles.js && prettier --config ../../.prettierrc --write \"lib/theme/**/*.js\"",
"watch": "run-p -c copy:watch build:watch",
"build:watch": "tsc --build --watch",
"copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch"
},
"dependencies": {
"@docusaurus/core": "2.1.0",
"@docusaurus/module-type-aliases": "2.1.0",
"@docusaurus/theme-common": "2.1.0",
"@docusaurus/types": "^2.1.0",
"@docusaurus/utils-validation": "2.1.0",
"@mdx-js/react": "^1.6.22",
"mermaid": "^9.1.1",
"tslib": "^2.4.0"
},
"devDependencies": {
"@types/mdx-js__react": "^1.5.5",
"@types/mermaid": "^8.2.9",
"react-test-renderer": "^17.0.2"
},
"peerDependencies": {
"react": "^16.8.4 || ^17.0.0",
"react-dom": "^16.8.4 || ^17.0.0"
},
"engines": {
"node": ">=16.14"
}
}

0 comments on commit 433f08b

Please sign in to comment.