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

Conversation

sjwall
Copy link
Contributor

@sjwall sjwall commented May 25, 2022

Pre-flight checklist

Note for third-party plugin authors using mdx loader

You should pass this new mdx loader option:

const loader = {
  loader: require.resolve('@docusaurus/mdx-loader'),
  options: {
    markdownConfig: siteConfig.markdown,
  },
}

Motivation

#1258 Have Mermaid diagrams supported OOTB. Merged code from mdx-mermaid library

Test Plan

There are unit tests for the remark plugin. There are also diagram examples from the Mermaid docs in the dogfooding pages

For the config here is an example docusaurus.config.js themeConfig:

themeConfig:
    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    ({
      mermaid: {
        theme: {
          light: 'dark',
          dark: 'forest'
        },
        config: {
          // Mermaid config
        }
      },
  })

Test links

Deploy preview:

Local:

Related issues/PRs

@facebook-github-bot facebook-github-bot added the CLA Signed Signed Facebook CLA label May 25, 2022
@Josh-Cena Josh-Cena added the pr: new feature This PR adds a new API or behavior. label May 25, 2022
@Josh-Cena Josh-Cena changed the title feat: add mermaid diagram support ootb #1258 feat: support mermaid code blocks in Markdown May 25, 2022
@netlify
Copy link

netlify bot commented May 25, 2022

[V2]

Name Link
🔨 Latest commit 1377f4a
🔍 Latest deploy log https://app.netlify.com/sites/docusaurus-2/deploys/63497ee6d6a0660009ec620b
😎 Deploy Preview https://deploy-preview-7490--docusaurus-2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@github-actions
Copy link

github-actions bot commented May 25, 2022

⚡️ Lighthouse report for the deploy preview of this PR

URL Performance Accessibility Best Practices SEO PWA Report
/ 🟠 86 🟢 98 🟢 100 🟢 100 🟠 80 Report
/docs/installation 🟠 77 🟢 100 🟢 100 🟢 100 🟢 90 Report

Copy link
Collaborator

@Josh-Cena Josh-Cena left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to make this opt-in.

Before we allow plugins to provide Markdown plugins (#6370), what about keeping the MDX loader part but hiding it behind a siteConfig.markdown.mermaid option that defaults to false, and also create another @docusaurus/theme-mermaid package for the theme components?

@sjwall
Copy link
Contributor Author

sjwall commented May 25, 2022

I shall have a look at making those 2 changes. Should I move the mermaid and theme config into siteConfig.markdown.mermaid?

Something like:

export type DocusaurusConfig = {
  markdown?: {
    mermaid?: boolean | {
      theme?: {
        light: mermaidAPI.Theme;
        dark: mermaidAPI.Theme;
        [htmlTheme: string]: mermaidAPI.Theme;
      };
      config?: mermaidAPI.Config;
    }
  }
}

@Josh-Cena
Copy link
Collaborator

Josh-Cena commented May 25, 2022

Theme options should be still in theme config. The markdown.mermaid option will be read by the MDX loader only to decide whether the mermaid plugin should be loaded. It's a bit redundant now, but in the future when it's populated by more definitions it will make more sense.

@Josh-Cena
Copy link
Collaborator

Sorry, left a bunch of random review comments... There's a bit left to be desired in this PR's approach. Let me know if you need help with any of the refactors. We are not in a rush anyways.

@Josh-Cena Josh-Cena marked this pull request as draft May 27, 2022 08:02
@sjwall
Copy link
Contributor Author

sjwall commented May 27, 2022

Sorry, left a bunch of random review comments... There's a bit left to be desired in this PR's approach. Let me know if you need help with any of the refactors. We are not in a rush anyways.

No worries, I wasn't at all familair with how Swizzle works before this PR so there was bound to be teething problems :) Hopefully now all good 🤞

Copy link
Collaborator

@Josh-Cena Josh-Cena left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is starting to look good!

I don't have much feedback for you to change. I'll play with this myself over the following days and push to your branch.

Comment on lines 17 to 18
// Assign a unique ID to each mermaid svg as per requirements of
// `mermaid.render`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very unsafe to have every effect mutate something... Effects aren't guaranteed to run in any order or run at any particular time, so this is practically not much better than assigning a random number to each SVG. This should be fixable with React 18's useId hook?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, shouldn't be an issue for now though 🤞

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CleanShot 2022-10-07 at 18 14 02@2x

All diagrams on the same page will have the exact same ID because the counter is distinct for each instance.

I don't understand why Mermaid want an ID, can you explain?

If it's only used client-side, you could just wrap the component in <BrowserOnly> and generate a random number for each instance? (ie no need to increment)

Not even documented: mermaid.render returns the svg string
Using the documented form is un-necessary
*/
return mermaid.render(mermaidId, txt);

Check warning

Code scanning / CodeQL

Unsafe HTML constructed from library input

[Markdown rendering](1) which depends on [library input](2) might later allow [cross-site scripting](3).
@slorber
Copy link
Collaborator

slorber commented Oct 14, 2022

Note for future self: I'm removing the MDXComponents from the Mermaid theme:

import MDXComponents from '@theme-init/MDXComponents';
import Mermaid from '@theme/Mermaid';

export default {
  ...MDXComponents,
  mermaid: Mermaid,
};

We want the mermaid theme to be able to register a theme component to the MDX context so that mdx loader can render it. Unfortunately, we want a plugin lifecycle API to allow it, but we don't have it yet.

The code above is not ideal because we can only wrap and "enhance" MDXComponents once, cf my comment (#7490 (comment)) and #4530, so I'd prefer not to use this solution.

Instead I'm doing like the SearchBar: render nothing by default in the theme classic, and let the theme enhancer override the implementation. Having a NOOP Mermaid component in theme-classic allows it to register it automatically to the MDXComponents so that we don't need to enhance this map

@slorber
Copy link
Collaborator

slorber commented Oct 14, 2022

Note: this implementation does not support server-side-rendering and has a few limitations:

  • does not work without JS, no progressive enhancement
  • produces layout shifts on page load, due to diagrams appearing after React hydration

Unfortunately Mermaid does not make it easy to pre-render SVGs at build time (see mermaid-js/mermaid#3650 (comment)).

It would require to run a headless browser like Puppeteer, and for dark/light mode support we would have to build each diagram twice, which is also not ideal. For now let's keep things simple and only render client-side with the known limitations.

@slorber slorber merged commit 9c92a79 into facebook:main Oct 14, 2022
@SimenB
Copy link
Contributor

SimenB commented Oct 14, 2022

Wooooooooo 🎉

@slorber slorber added the to backport This PR is planned to be backported to a stable version of Docusaurus label Oct 15, 2022
slorber pushed a commit that referenced this pull request Oct 28, 2022
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
@slorber slorber added backported This PR has been backported to a stable version of Docusaurus and removed to backport This PR is planned to be backported to a stable version of Docusaurus labels Nov 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backported This PR has been backported to a stable version of Docusaurus CLA Signed Signed Facebook CLA pr: new feature This PR adds a new API or behavior.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

OOTB Mermaid code block