fix(mdx-loader): support nested admonitions #8303

This commit is contained in:
Balthasar Hofer 2022-11-23 21:19:29 +01:00 committed by sebastienlorber
parent cf3ec180c2
commit 3f55453b8c
6 changed files with 217 additions and 8 deletions

View file

@ -11,7 +11,7 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Admonition from '@theme/Admonition';
In addition to the basic Markdown syntax, we use [remark-admonitions](https://github.com/elviswolcott/remark-admonitions) alongside MDX to add support for admonitions. Admonitions are wrapped by a set of 3 colons.
In addition to the basic Markdown syntax, we have a special admonitions syntax by wrapping text with a set of 3 colons, followed by a label denoting its type.
Example:
@ -107,7 +107,7 @@ Hello world
## Specifying title {#specifying-title}
You may also specify an optional title
You may also specify an optional title.
```md
:::note Your Title
@ -204,3 +204,128 @@ The types that are accepted are the same as above: `note`, `tip`, `danger`, `inf
</Admonition>
</BrowserWindow>
```
## Customizing admonitions {#customizing-admonitions}
There are two kinds of customizations possible with admonitions: **parsing** and **rendering**.
### Customizing rendering behavior {#customizing-rendering-behavior}
You can customize how each individual admonition type is rendered through [swizzling](../../swizzling.md). You can often achieve your goal through a simple wrapper. For example, in the follow example, we swap out the icon for `info` admonitions only.
```jsx title="src/theme/Admonition.js"
import React from 'react';
import Admonition from '@theme-original/Admonition';
import MyCustomNoteIcon from '@site/static/img/info.svg';
export default function AdmonitionWrapper(props) {
if (props.type !== 'info') {
return <Admonition title="My Custom Admonition Title" {...props} />;
}
return <Admonition icon={<MyCustomNoteIcon />} {...props} />;
}
```
### Customizing parsing behavior {#customizing-parsing-behavior}
Admonitions are implemented with a [Remark plugin](./markdown-features-plugins.mdx). The plugin is designed to be configurable. To customize the Remark plugin for a specific content plugin (docs, blog, pages), pass the options through the `admonitions` key.
```js title="docusaurus.config.js"
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
admonitions: {
tag: ':::',
keywords: ['note', 'tip', 'info', 'caution', 'danger'],
extendDefaults: true,
},
},
},
],
],
};
```
The plugin accepts the following options:
- `tag`: The tag that encloses the admonition. Defaults to `:::`.
- `keywords`: An array of keywords that can be used as the type for the admonition.
- `extendDefaults`: Should the provided options (such as `keywords`) be merged into the existing defaults. Defaults to `false`.
The `keyword` will be passed as the `type` prop of the `Admonition` component.
### Custom admonition type components {#custom-admonition-type-components}
By default, the theme doesn't know what do to with custom admonition keywords such as `:::my-custom-admonition`. It is your responsibility to map each admonition keyword to a React component so that the theme knows how to render them.
If you registered a new admonition type `my-custom-admonition` via the following config:
```js title="docusaurus.config.js"
module.exports = {
// ...
presets: [
[
'classic',
{
// ...
docs: {
admonitions: {
tag: ':::',
keywords: ['my-custom-admonition'],
extendDefaults: true,
},
},
},
],
],
};
```
You can provide the corresponding React component for `:::my-custom-admonition` by creating the following file (unfortunately, since it's not a React component file, it's not swizzlable):
```js title="src/theme/Admonition/Types.js"
import React from 'react';
import DefaultAdmonitionTypes from '@theme-original/Admonition/Types';
function MyCustomAdmonition(props) {
return (
<div style={{border: 'solid red', padding: 10}}>
<h5 style={{color: 'blue', fontSize: 30}}>{props.title}</h5>
<div>{props.children}</div>
</div>
);
}
const AdmonitionTypes = {
...DefaultAdmonitionTypes,
// Add all your custom admonition types here...
// You can also override the default ones if you want
'my-custom-admonition': MyCustomAdmonition,
};
export default AdmonitionTypes;
```
Now you can use your new admonition keyword in a Markdown file, and it will be parsed and rendered with your custom logic:
```md
:::my-custom-admonition Custom Admonition
It works!
:::
```
<BrowserWindow>
:::my-custom-admonition Custom Admonition
It works!
:::
</BrowserWindow>