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 16 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": "2.0.0-beta.21",
"@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",
"remark": "^12.0.1",
Expand Down
30 changes: 17 additions & 13 deletions 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 @@ -60,19 +62,20 @@ export type MDXOptions = {
beforeDefaultRehypePlugins: MDXPlugin[];
};

export type Options = Partial<MDXOptions> & {
staticDirs: string[];
siteDir: string;
isMDXPartial?: (filePath: string) => boolean;
isMDXPartialFrontMatterWarningDisabled?: boolean;
removeContentTitle?: boolean;
metadataPath?: string | ((filePath: string) => string);
createAssets?: (metadata: {
frontMatter: {[key: string]: unknown};
metadata: {[key: string]: unknown};
}) => {[key: string]: unknown};
filepath: string;
};
export type Options = Partial<MDXOptions> &
MarkdownConfig & {
staticDirs: string[];
siteDir: string;
isMDXPartial?: (filePath: string) => boolean;
isMDXPartialFrontMatterWarningDisabled?: boolean;
removeContentTitle?: boolean;
metadataPath?: string | ((filePath: string) => string);
createAssets?: (metadata: {
frontMatter: {[key: string]: unknown};
metadata: {[key: string]: unknown};
}) => {[key: string]: unknown};
filepath: string;
};

/**
* When this throws, it generally means that there's no metadata file associated
Expand Down Expand Up @@ -171,6 +174,7 @@ export async function mdxLoader(
...(reqOptions.beforeDefaultRemarkPlugins ?? []),
...getAdmonitionsPlugins(reqOptions.admonitions ?? false),
...DEFAULT_OPTIONS.remarkPlugins,
...(reqOptions.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 @@ -460,6 +460,7 @@ export default async function pluginContentBlog(
(author) => author.imageURL,
),
}),
...siteConfig.markdown,
},
},
{
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus-plugin-content-docs/src/index.ts
Expand Up @@ -380,6 +380,7 @@ export default async function pluginContentDocs(
}) => ({
image: frontMatter.image,
}),
...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`,
);
},
...siteConfig.markdown,
slorber marked this conversation as resolved.
Show resolved Hide resolved
},
},
{
Expand Down
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)
44 changes: 44 additions & 0 deletions packages/docusaurus-theme-mermaid/package.json
@@ -0,0 +1,44 @@
{
"name": "@docusaurus/theme-mermaid",
"version": "2.0.0-beta.21",
"description": "Mermaid components for Docusaurus.",
"main": "lib/index.js",
"types": "src/theme-mermaid.d.ts",
"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.0.0-beta.21",
"@docusaurus/module-type-aliases": "2.0.0-beta.21",
"@docusaurus/theme-common": "2.0.0-beta.21",
"@docusaurus/types": "2.0.0-beta.21",
"@docusaurus/utils-validation": "2.0.0-beta.21",
"@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,0 +1,75 @@
/**
* 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 {
validateThemeConfig,
DEFAULT_THEME_CONFIG,
} from '../validateThemeConfig';
import type {Joi} from '@docusaurus/utils-validation';
import type {ThemeConfig, UserThemeConfig} from '@docusaurus/theme-mermaid';

function testValidateThemeConfig(themeConfig: UserThemeConfig) {
function validate(
schema: Joi.ObjectSchema<ThemeConfig>,
cfg: UserThemeConfig,
) {
const {value, error} = schema.validate(cfg, {
convert: false,
});
if (error) {
throw error;
}
return value;
}

return validateThemeConfig({validate, themeConfig});
}

describe('validateThemeConfig', () => {
it('undefined config', () => {
const mermaid = undefined;
expect(testValidateThemeConfig({mermaid})).toEqual(DEFAULT_THEME_CONFIG);
});

it('nonexistent config', () => {
expect(testValidateThemeConfig({})).toEqual(DEFAULT_THEME_CONFIG);
});

it('empty config', () => {
const mermaid = {};
expect(testValidateThemeConfig({mermaid})).toEqual(DEFAULT_THEME_CONFIG);
});

it('theme', () => {
const mermaid = {
theme: {
light: 'light',
dark: 'dark',
},
};
expect(testValidateThemeConfig({mermaid})).toEqual({
mermaid: {
...DEFAULT_THEME_CONFIG.mermaid,
...mermaid,
},
});
});

it('mermaidOptions', () => {
const mermaid = {
mermaidOptions: {
fontFamily: 'Ariel',
},
};
expect(testValidateThemeConfig({mermaid})).toEqual({
mermaid: {
...DEFAULT_THEME_CONFIG.mermaid,
...mermaid,
},
});
});
});
23 changes: 23 additions & 0 deletions packages/docusaurus-theme-mermaid/src/index.ts
@@ -0,0 +1,23 @@
/**
* 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 type {Plugin} from '@docusaurus/types';

export default function themeMermaid(): Plugin<void> {
return {
name: 'docusaurus-theme-mermaid',

getThemePath() {
return '../lib/theme';
},
getTypeScriptThemePath() {
return '../src/theme';
},
};
}

export {validateThemeConfig} from './validateThemeConfig';