Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support mermaid code blocks in Markdown #7490

Merged
merged 33 commits into from Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
54ee20f
feat: add mermaid diagram support ootb #1258
sjwall May 24, 2022
a003697
feat(mdx-loader): mermaid rendering optional
sjwall May 26, 2022
ed1f044
refactor: move mermaid components to own package
sjwall May 27, 2022
ed1f21c
refactor: remove theme-classic mermaid dependency
sjwall May 27, 2022
777c086
refactor(mdx-loader): markdown config option
sjwall May 27, 2022
3a32f60
refactor(theme-mermaid): remove exports
sjwall May 27, 2022
11836a0
little refactors
Josh-Cena May 27, 2022
5d836f5
Merge branch 'main' into mermaid
Josh-Cena May 27, 2022
8c9e005
remove unused
Josh-Cena May 27, 2022
722f75b
remark plugin refactor
Josh-Cena May 29, 2022
c0a17ac
Merge branch 'main' into mermaid
Josh-Cena May 29, 2022
0a5e372
greatly simplify
Josh-Cena May 29, 2022
73f53a8
simplify API
Josh-Cena May 29, 2022
ec6f920
fix tests
Josh-Cena May 29, 2022
47bec9b
move dogfooding
Josh-Cena May 29, 2022
be53cf3
Merge branch 'main' into mermaid
sjwall Jun 6, 2022
addacc6
Merge branch 'main' into mermaid
Josh-Cena Jun 15, 2022
51b6c48
Merge branch 'main' into mermaid
slorber Oct 7, 2022
5ec7c0b
mermaid.mermaidOptions => mermaid.options
slorber Oct 13, 2022
25cb8aa
validate config.markdown.mermaid
slorber Oct 13, 2022
56ca9c7
do not spread markdown config to mdx loader: be more explicit with at…
slorber Oct 13, 2022
9772c2e
typo
slorber Oct 13, 2022
5d49364
temp better mermaid integration
slorber Oct 13, 2022
062ed20
expose mermaid hooks as client apis instead of themes
slorber Oct 13, 2022
4da56ed
fix snapshots
slorber Oct 14, 2022
b6c408d
good mermaid integration
slorber Oct 14, 2022
d5ca004
increase random count
slorber Oct 14, 2022
76c8703
add max-width 100% to container/svg
slorber Oct 14, 2022
c8d1e2c
try to fix journey bug
slorber Oct 14, 2022
bd67df1
fix bad project-words merge
slorber Oct 14, 2022
8c88c55
refactor MDXComponents usage
slorber Oct 14, 2022
57d481c
add mermaid in tabs dogfood, see https://github.com/sjwall/mdx-mermai…
slorber Oct 14, 2022
1377f4a
````mdx-code-block
slorber Oct 14, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/docusaurus-mdx-loader/package.json
Expand Up @@ -40,6 +40,7 @@
"@docusaurus/types": "^3.0.0-alpha.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 @@ -288,6 +288,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 @@ -897,6 +897,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 @@ -913,6 +914,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 @@ -1221,6 +1223,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": "3.0.0-alpha.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": "^3.0.0-alpha.0",
"@docusaurus/module-type-aliases": "^3.0.0-alpha.0",
"@docusaurus/theme-common": "^3.0.0-alpha.0",
"@docusaurus/types": "^3.0.0-alpha.0",
"@docusaurus/utils-validation": "^3.0.0-alpha.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"
}
}