mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-06 11:27:54 +02:00
docs: rewrite some docs for mdx v2 (#8941)
Co-authored-by: Balthasar Hofer <lebalz@outlook.com> Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
This commit is contained in:
parent
2cae24fe5f
commit
7e09ae0c57
3 changed files with 72 additions and 261 deletions
|
@ -18,6 +18,7 @@ autoconverted
|
||||||
autogen
|
autogen
|
||||||
autogenerating
|
autogenerating
|
||||||
autohide
|
autohide
|
||||||
|
autolinks
|
||||||
backport
|
backport
|
||||||
backticks
|
backticks
|
||||||
bartosz
|
bartosz
|
||||||
|
@ -48,6 +49,7 @@ codegen
|
||||||
codeql
|
codeql
|
||||||
codesandbox
|
codesandbox
|
||||||
codespaces
|
codespaces
|
||||||
|
commonmark
|
||||||
contravariance
|
contravariance
|
||||||
corejs
|
corejs
|
||||||
crawlable
|
crawlable
|
||||||
|
|
|
@ -18,7 +18,7 @@ And the answer is: create an MDX plugin! MDX has a built-in [plugin system](http
|
||||||
- Creating remark/rehype plugins to transform the elements generated by existing MDX syntax;
|
- Creating remark/rehype plugins to transform the elements generated by existing MDX syntax;
|
||||||
- Creating remark/rehype plugins to introduce new syntaxes to MDX.
|
- Creating remark/rehype plugins to introduce new syntaxes to MDX.
|
||||||
|
|
||||||
If you play with the [MDX playground](https://mdx-git-renovate-babel-monorepo-mdx.vercel.app/playground), you would notice that the MDX transpilation has two intermediate steps: Markdown AST (MDAST), and Hypertext AST (HAST), before arriving at the final JSX output. MDX plugins also come in two forms:
|
If you play with the [MDX playground](https://mdxjs.com/playground/), you would notice that the MDX transpilation has two intermediate steps: Markdown AST (MDAST), and Hypertext AST (HAST), before arriving at the final JSX output. MDX plugins also come in two forms:
|
||||||
|
|
||||||
- **[Remark](https://github.com/remarkjs/remark/)**: processes the Markdown AST.
|
- **[Remark](https://github.com/remarkjs/remark/)**: processes the Markdown AST.
|
||||||
- **[Rehype](https://github.com/rehypejs/rehype/)**: processes the Hypertext AST.
|
- **[Rehype](https://github.com/rehypejs/rehype/)**: processes the Hypertext AST.
|
||||||
|
@ -45,15 +45,9 @@ These are all typical use-cases of Remark plugins, which can also be a source of
|
||||||
An MDX plugin is usually an npm package, so you install them like other npm packages using npm. Take the [math plugins](./markdown-features-math-equations.mdx) as an example.
|
An MDX plugin is usually an npm package, so you install them like other npm packages using npm. Take the [math plugins](./markdown-features-math-equations.mdx) as an example.
|
||||||
|
|
||||||
```bash npm2yarn
|
```bash npm2yarn
|
||||||
npm install --save remark-math@3 rehype-katex@4
|
npm install --save remark-math@5 rehype-katex@6
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
There's recently a trend in the Remark/Rehype ecosystem to migrate to ES Modules, a new JavaScript module system, which Docusaurus doesn't support yet. Please make sure your installed plugin version is CommonJS-compatible before we officially support ESM. Alternatively, you can read about using dynamic `import()` as a workaround in the tutorial of installing [`rehype-katex`](./markdown-features-math-equations.mdx#upgrading-rehype-katex-beyond-recommended-version).
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>How are <code>remark-math</code> and <code>rehype-katex</code> different?</summary>
|
<summary>How are <code>remark-math</code> and <code>rehype-katex</code> different?</summary>
|
||||||
|
|
||||||
|
@ -63,30 +57,34 @@ Next, the `rehype-katex` operates on the Hypertext AST where everything has been
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
Next, add them to the plugin options through plugin or preset config in `docusaurus.config.js`:
|
:::caution
|
||||||
|
|
||||||
|
Many official Remark/Rehype plugins are using ES Modules, a new JavaScript module system, which Docusaurus doesn't support yet. To work around this issue, we recommend to use dynamic `import()` inside an `async` config creation function.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Next, add them to the plugin options through plugin or preset config in `docusaurus.config.js`, using dynamic `import()`:
|
||||||
|
|
||||||
```js title="docusaurus.config.js"
|
```js title="docusaurus.config.js"
|
||||||
// highlight-start
|
// highlight-start
|
||||||
const math = require('remark-math');
|
module.exports = async function createConfigAsync() {
|
||||||
const katex = require('rehype-katex');
|
// highlight-end
|
||||||
// highlight-end
|
return {
|
||||||
|
presets: [
|
||||||
module.exports = {
|
[
|
||||||
title: 'Docusaurus',
|
'@docusaurus/preset-classic',
|
||||||
tagline: 'Build optimized websites quickly, focus on your content',
|
{
|
||||||
presets: [
|
docs: {
|
||||||
[
|
path: 'docs',
|
||||||
'@docusaurus/preset-classic',
|
// highlight-start
|
||||||
{
|
remarkPlugins: [(await import('remark-math')).default],
|
||||||
docs: {
|
rehypePlugins: [(await import('rehype-katex')).default],
|
||||||
// highlight-start
|
// highlight-end
|
||||||
remarkPlugins: [math],
|
},
|
||||||
rehypePlugins: [katex],
|
|
||||||
// highlight-end
|
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
],
|
],
|
||||||
],
|
};
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -95,21 +93,23 @@ module.exports = {
|
||||||
Some plugins can be configured and accept their own options. In that case, use the `[plugin, pluginOptions]` syntax, like this:
|
Some plugins can be configured and accept their own options. In that case, use the `[plugin, pluginOptions]` syntax, like this:
|
||||||
|
|
||||||
```js title="docusaurus.config.js"
|
```js title="docusaurus.config.js"
|
||||||
module.exports = {
|
module.exports = async function createConfigAsync() {
|
||||||
presets: [
|
return {
|
||||||
[
|
presets: [
|
||||||
'@docusaurus/preset-classic',
|
[
|
||||||
{
|
'@docusaurus/preset-classic',
|
||||||
docs: {
|
{
|
||||||
remarkPlugins: [math],
|
docs: {
|
||||||
rehypePlugins: [
|
rehypePlugins: [
|
||||||
// highlight-next-line
|
// highlight-start
|
||||||
[katex, {strict: false}],
|
[(await import('rehype-katex')).default, {strict: false}],
|
||||||
],
|
// highlight-end
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
],
|
],
|
||||||
],
|
};
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -17,14 +17,29 @@ import styles from './markdown-features-react.module.css';
|
||||||
|
|
||||||
Docusaurus has built-in support for [MDX v2](https://mdxjs.com/), which allows you to write JSX within your Markdown files and render them as React components.
|
Docusaurus has built-in support for [MDX v2](https://mdxjs.com/), which allows you to write JSX within your Markdown files and render them as React components.
|
||||||
|
|
||||||
:::note
|
:::info MDX vs. CommonMark
|
||||||
|
|
||||||
While Docusaurus parses both `.md` and `.mdx` files using MDX, some of the syntaxes are treated slightly differently by third-party tools. For the most accurate parsing and better editor support, we recommend using the `.mdx` extension for files containing MDX syntax.
|
Docusaurus parses both `.md` and `.mdx` files using MDX, but **the syntax is interpreted differently based on the file extension**:
|
||||||
|
|
||||||
|
- With the `.md` extension, the parser is compatible with [CommonMark](https://commonmark.org/) and does not allow the usage of JSX.
|
||||||
|
- With the `.mdx` extension, the parser is stricter than [CommonMark](https://commonmark.org/) and is not 100% compatible with it, but it becomes possible to use JSX.
|
||||||
|
|
||||||
|
It is also possible to override the file extension format with front matter: `format: mdx`.
|
||||||
|
|
||||||
|
The rest of this page assumes usage of the `mdx` format.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Check out the [MDX docs](https://mdxjs.com/) to see what other fancy stuff you can do with MDX.
|
Check out the [MDX docs](https://mdxjs.com/) to see what other fancy stuff you can do with MDX.
|
||||||
|
|
||||||
|
:::tip Debugging MDX
|
||||||
|
|
||||||
|
The MDX format is quite strict, and you may get compilation errors.
|
||||||
|
|
||||||
|
Use the **[MDX playground](https://mdxjs.com/playground/)** to debug them and make sure your syntax is valid.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
### Exporting components {#exporting-components}
|
### Exporting components {#exporting-components}
|
||||||
|
|
||||||
To define any custom component within an MDX file, you have to export it: only paragraphs that start with `export` will be parsed as components instead of prose.
|
To define any custom component within an MDX file, you have to export it: only paragraphs that start with `export` will be parsed as components instead of prose.
|
||||||
|
@ -84,10 +99,6 @@ Since all doc files are parsed using MDX, anything that looks like HTML is actua
|
||||||
<span style={{backgroundColor: 'red'}}>Foo</span>
|
<span style={{backgroundColor: 'red'}}>Foo</span>
|
||||||
```
|
```
|
||||||
|
|
||||||
This behavior is different from Docusaurus 1. See also [Migrating from v1 to v2](../../migration/migration-manual.mdx#convert-style-attributes-to-style-objects-in-mdx).
|
|
||||||
|
|
||||||
In addition, MDX is not [100% compatible with CommonMark](https://github.com/facebook/docusaurus/issues/3018). Use the **[MDX playground](https://mdx-git-renovate-babel-monorepo-mdx.vercel.app/playground)** to ensure that your syntax is valid MDX.
|
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### Importing components {#importing-components}
|
### Importing components {#importing-components}
|
||||||
|
@ -204,7 +215,7 @@ From MDX v2+ onward (Docusaurus v3+), lower-case tag names are always rendered a
|
||||||
|
|
||||||
:::caution
|
:::caution
|
||||||
|
|
||||||
This feature is powered by [a wrapper provider](https://mdx-git-renovate-babel-monorepo-mdx.vercel.app/advanced/components#mdxprovider). If you are importing Markdown in a React page, you have to supply this provider yourself through the `MDXContent` theme component.
|
This feature is powered by [an `MDXProvider`](https://mdxjs.com/docs/using-mdx/#mdx-provider). If you are importing Markdown in a React page, you have to supply this provider yourself through the `MDXContent` theme component.
|
||||||
|
|
||||||
```jsx title="src/pages/index.js"
|
```jsx title="src/pages/index.js"
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
@ -231,227 +242,25 @@ If you don't wrap your imported MDX with `MDXContent`, the global scope will not
|
||||||
|
|
||||||
### Markdown and JSX interoperability {#markdown-and-jsx-interoperability}
|
### Markdown and JSX interoperability {#markdown-and-jsx-interoperability}
|
||||||
|
|
||||||
Docusaurus v2 is using MDX v1, which has a lot of known cases where the content fails to be correctly parsed as Markdown. Use the **[MDX playground](https://mdx-git-renovate-babel-monorepo-mdx.vercel.app/playground)** to ensure that your syntax is valid MDX.
|
Docusaurus v3 is using [MDX v2](https://mdxjs.com/blog/v2/).
|
||||||
|
|
||||||
<details>
|
The [MDX syntax](https://mdxjs.com/docs/what-is-mdx/#mdx-syntax) is mostly compatible with [CommonMark](https://commonmark.org/), but is much stricter because your `.mdx` files are compiled into real React components (check the [playground](https://mdxjs.com/playground/)).
|
||||||
<summary>Samples of parsing failures</summary>
|
|
||||||
|
|
||||||
**A paragraph starting with a JSX tag will be seen entirely as a JSX string:**
|
Some valid CommonMark features won't work with MDX ([more info](https://mdxjs.com/docs/what-is-mdx/#markdown)), notably:
|
||||||
|
|
||||||
```mdx-code-block
|
- Indented code blocks: use triple backticks instead
|
||||||
<Tabs groupId="jsx-and-md">
|
- Autolinks (`<http://localhost:3000>`): use regular link syntax instead (`[http://localhost:3000](http://localhost:3000)`)
|
||||||
<TabItem value="Problem">
|
- HTML syntax (`<p style="color: red;">`): use JSX instead (`<p style={{color: 'red'}}>`)
|
||||||
<div className={styles.wrappingBlock}>
|
- Unescaped `{` and `<`: escape them with `\` instead (`\{` and `\<`)
|
||||||
```
|
|
||||||
|
|
||||||
```jsx
|
:::tip
|
||||||
<span style={{color: 'red'}}>Highlighted text</span> but afterwards _Markdown_ **doesn't work**
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
In case you need a less strict format, with [CommonMark](https://commonmark.org/) compatibility, you can use:
|
||||||
</div>
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
<BrowserWindow>
|
|
||||||
|
|
||||||
<span style={{color: 'red'}}>Highlighted text</span> but afterwards _Markdown_ **doesn't work**
|
- The `.md` file extension instead of `.mdx`
|
||||||
|
- The `format: md` front matter
|
||||||
|
|
||||||
</BrowserWindow>
|
:::
|
||||||
</div>
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="Workaround">
|
|
||||||
|
|
||||||
Use JSX for the rest of the line, or prefix the line with some plain text:
|
|
||||||
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
```
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
<span style={{color: 'red'}}>Use JSX for the paragraph</span> to stop <i>worrying about</i> <b>Markdown</b>
|
|
||||||
|
|
||||||
​<span style={{color: 'red'}}>← This is a zero-width space</span> and afterwards _Markdown_ **works**
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
</div>
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
<BrowserWindow>
|
|
||||||
|
|
||||||
<span style={{color: 'red'}}>Use JSX for the paragraph</span> to stop <i>worrying about</i> <b>Markdown</b>
|
|
||||||
|
|
||||||
​<span style={{color: 'red'}}>← This is a zero-width space</span> and afterwards _Markdown_ **works**
|
|
||||||
|
|
||||||
</BrowserWindow>
|
|
||||||
</div>
|
|
||||||
</TabItem>
|
|
||||||
</Tabs>
|
|
||||||
|
|
||||||
**Markdown within a JSX tag never works:**
|
|
||||||
|
|
||||||
<Tabs groupId="jsx-and-md">
|
|
||||||
<TabItem value="Problem">
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
```
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
<span style={{color: 'red'}}>**Bold doesn't work**</span>
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
</div>
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
<BrowserWindow>
|
|
||||||
|
|
||||||
<span style={{color: 'red'}}>**Bold doesn't work**</span>
|
|
||||||
|
|
||||||
</BrowserWindow>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="Workaround">
|
|
||||||
|
|
||||||
Use JSX within JSX tag, or move the Markdown to the outer layer:
|
|
||||||
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
```
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
<span style={{color: 'red'}}><b>Bold now works</b></span>
|
|
||||||
|
|
||||||
**<span style={{color: 'red'}}>Bold now works</span>**
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
</div>
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
<BrowserWindow>
|
|
||||||
|
|
||||||
<span style={{color: 'red'}}><b>Bold now works</b></span>
|
|
||||||
|
|
||||||
**<span style={{color: 'red'}}>Bold now works</span>**
|
|
||||||
|
|
||||||
</BrowserWindow>
|
|
||||||
</div>
|
|
||||||
</TabItem>
|
|
||||||
</Tabs>
|
|
||||||
|
|
||||||
**Text immediately below a JSX tag will be seen as JSX text:**
|
|
||||||
|
|
||||||
<Tabs groupId="jsx-and-md">
|
|
||||||
<TabItem value="Problem">
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
```
|
|
||||||
|
|
||||||
{/* prettier-ignore */}
|
|
||||||
```jsx
|
|
||||||
<div style={{color: 'red'}}>
|
|
||||||
**Bold still doesn't work**
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
</div>
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
<BrowserWindow>
|
|
||||||
|
|
||||||
<div style={{color: 'red'}}>
|
|
||||||
**Bold still doesn't work**
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</BrowserWindow>
|
|
||||||
</div>
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="Workaround">
|
|
||||||
|
|
||||||
Add an empty new line:
|
|
||||||
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
```
|
|
||||||
|
|
||||||
{/* prettier-ignore */}
|
|
||||||
```jsx
|
|
||||||
<div style={{color: 'red'}}>
|
|
||||||
|
|
||||||
**Bold now works**
|
|
||||||
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
</div>
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
<BrowserWindow>
|
|
||||||
<div style={{color: 'red'}}>
|
|
||||||
|
|
||||||
**Bold now works**
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</BrowserWindow>
|
|
||||||
</div>
|
|
||||||
</TabItem>
|
|
||||||
</Tabs>
|
|
||||||
|
|
||||||
**Markdown text indented by four spaces will be seen as a code block:**
|
|
||||||
|
|
||||||
<Tabs groupId="jsx-and-md">
|
|
||||||
<TabItem value="Problem">
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
```
|
|
||||||
|
|
||||||
{/* prettier-ignore */}
|
|
||||||
```jsx
|
|
||||||
<div style={{color: 'red'}}>
|
|
||||||
|
|
||||||
You may think I'm just some text...
|
|
||||||
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
</div>
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
<BrowserWindow>
|
|
||||||
|
|
||||||
<div style={{color: 'red'}}>
|
|
||||||
|
|
||||||
You may think I'm just some text...
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</BrowserWindow>
|
|
||||||
</div>
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="Workaround">
|
|
||||||
|
|
||||||
Don't indent:
|
|
||||||
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
```
|
|
||||||
|
|
||||||
{/* prettier-ignore */}
|
|
||||||
```jsx
|
|
||||||
<div style={{color: 'red'}}>
|
|
||||||
|
|
||||||
Now I'm actually just text
|
|
||||||
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
</div>
|
|
||||||
<div className={styles.wrappingBlock}>
|
|
||||||
<BrowserWindow>
|
|
||||||
<div style={{color: 'red'}}>
|
|
||||||
|
|
||||||
Now I'm actually just text
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</BrowserWindow>
|
|
||||||
</div>
|
|
||||||
</TabItem>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Importing code snippets {#importing-code-snippets}
|
## Importing code snippets {#importing-code-snippets}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue