mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
refactor: handle all admonitions via JSX component (#7152)
Co-authored-by: Joshua Chen <sidachen2003@gmail.com> Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
17fe43ecc8
commit
5746c58f41
39 changed files with 709 additions and 250 deletions
4
jest/deps.d.ts
vendored
4
jest/deps.d.ts
vendored
|
@ -20,6 +20,10 @@ declare module 'remark-mdx' {
|
|||
export = mdx;
|
||||
}
|
||||
|
||||
declare module 'remark-rehype';
|
||||
|
||||
declare module 'rehype-stringify';
|
||||
|
||||
declare module '@testing-utils/git' {
|
||||
const createTempRepo: typeof import('./utils/git').createTempRepo;
|
||||
export {createTempRepo};
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
"@types/unist": "^2.0.6",
|
||||
"remark": "^12.0.1",
|
||||
"remark-mdx": "^1.6.21",
|
||||
"rehype-stringify": "^8.0.0",
|
||||
"remark-rehype": "^8.1.0",
|
||||
"to-vfile": "^6.1.0",
|
||||
"unist-builder": "^2.0.3",
|
||||
"unist-util-remove-position": "^3.0.0"
|
||||
|
|
|
@ -23,8 +23,10 @@ import unwrapMdxCodeBlocks from './remark/unwrapMdxCodeBlocks';
|
|||
import transformImage from './remark/transformImage';
|
||||
import transformLinks from './remark/transformLinks';
|
||||
|
||||
import transformAdmonitions from './remark/admonitions';
|
||||
import type {LoaderContext} from 'webpack';
|
||||
import type {Processor, Plugin} from 'unified';
|
||||
import type {AdmonitionOptions} from './remark/admonitions';
|
||||
|
||||
const {
|
||||
loaders: {inlineMarkdownImageFileLoader},
|
||||
|
@ -37,6 +39,7 @@ const pragma = `
|
|||
`;
|
||||
|
||||
const DEFAULT_OPTIONS: MDXOptions = {
|
||||
admonitions: true,
|
||||
rehypePlugins: [],
|
||||
remarkPlugins: [unwrapMdxCodeBlocks, emoji, headings, toc],
|
||||
beforeDefaultRemarkPlugins: [],
|
||||
|
@ -48,7 +51,9 @@ const compilerCache = new Map<string | Options, [Processor, Options]>();
|
|||
export type MDXPlugin =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[Plugin<any[]>, any] | Plugin<any[]>;
|
||||
|
||||
export type MDXOptions = {
|
||||
admonitions: boolean | AdmonitionOptions;
|
||||
remarkPlugins: MDXPlugin[];
|
||||
rehypePlugins: MDXPlugin[];
|
||||
beforeDefaultRemarkPlugins: MDXPlugin[];
|
||||
|
@ -132,6 +137,19 @@ function createAssetsExportCode(assets: unknown) {
|
|||
return `{\n${codeLines.join('\n')}\n}`;
|
||||
}
|
||||
|
||||
function getAdmonitionsPlugins(
|
||||
admonitionsOption: MDXOptions['admonitions'],
|
||||
): MDXPlugin[] {
|
||||
if (admonitionsOption) {
|
||||
const plugin: MDXPlugin =
|
||||
admonitionsOption === true
|
||||
? transformAdmonitions
|
||||
: [transformAdmonitions, admonitionsOption];
|
||||
return [plugin];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export async function mdxLoader(
|
||||
this: LoaderContext<Options>,
|
||||
fileString: string,
|
||||
|
@ -149,32 +167,37 @@ export async function mdxLoader(
|
|||
const hasFrontMatter = Object.keys(frontMatter).length > 0;
|
||||
|
||||
if (!compilerCache.has(this.query)) {
|
||||
const remarkPlugins: MDXPlugin[] = [
|
||||
...(reqOptions.beforeDefaultRemarkPlugins ?? []),
|
||||
...getAdmonitionsPlugins(reqOptions.admonitions ?? false),
|
||||
...DEFAULT_OPTIONS.remarkPlugins,
|
||||
[
|
||||
transformImage,
|
||||
{
|
||||
staticDirs: reqOptions.staticDirs,
|
||||
siteDir: reqOptions.siteDir,
|
||||
},
|
||||
],
|
||||
[
|
||||
transformLinks,
|
||||
{
|
||||
staticDirs: reqOptions.staticDirs,
|
||||
siteDir: reqOptions.siteDir,
|
||||
},
|
||||
],
|
||||
...(reqOptions.remarkPlugins ?? []),
|
||||
];
|
||||
|
||||
const rehypePlugins: MDXPlugin[] = [
|
||||
...(reqOptions.beforeDefaultRehypePlugins ?? []),
|
||||
...DEFAULT_OPTIONS.rehypePlugins,
|
||||
...(reqOptions.rehypePlugins ?? []),
|
||||
];
|
||||
|
||||
const options: Options = {
|
||||
...reqOptions,
|
||||
remarkPlugins: [
|
||||
...(reqOptions.beforeDefaultRemarkPlugins ?? []),
|
||||
...DEFAULT_OPTIONS.remarkPlugins,
|
||||
[
|
||||
transformImage,
|
||||
{
|
||||
staticDirs: reqOptions.staticDirs,
|
||||
siteDir: reqOptions.siteDir,
|
||||
},
|
||||
],
|
||||
[
|
||||
transformLinks,
|
||||
{
|
||||
staticDirs: reqOptions.staticDirs,
|
||||
siteDir: reqOptions.siteDir,
|
||||
},
|
||||
],
|
||||
...(reqOptions.remarkPlugins ?? []),
|
||||
],
|
||||
rehypePlugins: [
|
||||
...(reqOptions.beforeDefaultRehypePlugins ?? []),
|
||||
...DEFAULT_OPTIONS.rehypePlugins,
|
||||
...(reqOptions.rehypePlugins ?? []),
|
||||
],
|
||||
remarkPlugins,
|
||||
rehypePlugins,
|
||||
};
|
||||
compilerCache.set(this.query, [createCompiler(options), options]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2020 Elvis Wolcott
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,3 @@
|
|||
# Docusaurus admonitions
|
||||
|
||||
Code from [remark-admonitions](https://github.com/remarkjs/remark-directive) (MIT license) has been copied to this folder, and highly customized for Docusaurus needs.
|
25
packages/docusaurus-mdx-loader/src/remark/admonitions/__tests__/__fixtures__/base.md
generated
Normal file
25
packages/docusaurus-mdx-loader/src/remark/admonitions/__tests__/__fixtures__/base.md
generated
Normal file
|
@ -0,0 +1,25 @@
|
|||
The blog feature enables you to deploy in no time a full-featured blog.
|
||||
|
||||
:::info Sample Title
|
||||
|
||||
Check the [Blog Plugin API Reference documentation](./api/plugins/plugin-content-blog.md) for an exhaustive list of options.
|
||||
|
||||
:::
|
||||
|
||||
## Initial setup {#initial-setup}
|
||||
|
||||
To set up your site's blog, start by creating a `blog` directory.
|
||||
|
||||
:::tip
|
||||
|
||||
Use the **[Fast Track](introduction.md#fast-track)** to understand Docusaurus in **5 minutes ⏱**!
|
||||
|
||||
Use **[docusaurus.new](https://docusaurus.new)** to test Docusaurus immediately in your browser!
|
||||
|
||||
:::
|
||||
|
||||
++++tip
|
||||
|
||||
Admonition with different syntax
|
||||
|
||||
++++
|
7
packages/docusaurus-mdx-loader/src/remark/admonitions/__tests__/__fixtures__/interpolation.md
generated
Normal file
7
packages/docusaurus-mdx-loader/src/remark/admonitions/__tests__/__fixtures__/interpolation.md
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
Test admonition with interpolated title/body
|
||||
|
||||
:::tip My `interpolated` **title** <button style={{color: "red"}} onClick={() => alert("click")}>test</button>
|
||||
|
||||
`body` **interpolated** <button>content</button>
|
||||
|
||||
:::
|
|
@ -0,0 +1,44 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`admonitions remark plugin base 1`] = `
|
||||
"<p>The blog feature enables you to deploy in no time a full-featured blog.</p>
|
||||
<admonition title="Sample Title" type="info"><p>Check the <a href="./api/plugins/plugin-content-blog.md">Blog Plugin API Reference documentation</a> for an exhaustive list of options.</p></admonition>
|
||||
<h2>Initial setup {#initial-setup}</h2>
|
||||
<p>To set up your site's blog, start by creating a <code>blog</code> directory.</p>
|
||||
<admonition type="tip"><p>Use the <strong><a href="introduction.md#fast-track">Fast Track</a></strong> to understand Docusaurus in <strong>5 minutes ⏱</strong>!</p><p>Use <strong><a href="https://docusaurus.new">docusaurus.new</a></strong> to test Docusaurus immediately in your browser!</p></admonition>
|
||||
<p>++++tip</p>
|
||||
<p>Admonition with different syntax</p>
|
||||
<p>++++</p>"
|
||||
`;
|
||||
|
||||
exports[`admonitions remark plugin custom keywords 1`] = `
|
||||
"<p>The blog feature enables you to deploy in no time a full-featured blog.</p>
|
||||
<p>:::info Sample Title</p>
|
||||
<p>Check the <a href="./api/plugins/plugin-content-blog.md">Blog Plugin API Reference documentation</a> for an exhaustive list of options.</p>
|
||||
<p>:::</p>
|
||||
<h2>Initial setup {#initial-setup}</h2>
|
||||
<p>To set up your site's blog, start by creating a <code>blog</code> directory.</p>
|
||||
<admonition type="tip"><p>Use the <strong><a href="introduction.md#fast-track">Fast Track</a></strong> to understand Docusaurus in <strong>5 minutes ⏱</strong>!</p><p>Use <strong><a href="https://docusaurus.new">docusaurus.new</a></strong> to test Docusaurus immediately in your browser!</p></admonition>
|
||||
<p>++++tip</p>
|
||||
<p>Admonition with different syntax</p>
|
||||
<p>++++</p>"
|
||||
`;
|
||||
|
||||
exports[`admonitions remark plugin custom tag 1`] = `
|
||||
"<p>The blog feature enables you to deploy in no time a full-featured blog.</p>
|
||||
<p>:::info Sample Title</p>
|
||||
<p>Check the <a href="./api/plugins/plugin-content-blog.md">Blog Plugin API Reference documentation</a> for an exhaustive list of options.</p>
|
||||
<p>:::</p>
|
||||
<h2>Initial setup {#initial-setup}</h2>
|
||||
<p>To set up your site's blog, start by creating a <code>blog</code> directory.</p>
|
||||
<p>:::tip</p>
|
||||
<p>Use the <strong><a href="introduction.md#fast-track">Fast Track</a></strong> to understand Docusaurus in <strong>5 minutes ⏱</strong>!</p>
|
||||
<p>Use <strong><a href="https://docusaurus.new">docusaurus.new</a></strong> to test Docusaurus immediately in your browser!</p>
|
||||
<p>:::</p>
|
||||
<admonition type="tip"><p>Admonition with different syntax</p></admonition>"
|
||||
`;
|
||||
|
||||
exports[`admonitions remark plugin interpolation 1`] = `
|
||||
"<p>Test admonition with interpolated title/body</p>
|
||||
<admonition type="tip"><mdxAdmonitionTitle>My <code>interpolated</code> <strong>title</strong> <button style={{color: "red"}} onClick={() => alert("click")}>test</mdxAdmonitionTitle><p><code>body</code> <strong>interpolated</strong> content</p></admonition>"
|
||||
`;
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* 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 path from 'path';
|
||||
import remark from 'remark';
|
||||
import remark2rehype from 'remark-rehype';
|
||||
import stringify from 'rehype-stringify';
|
||||
|
||||
import vfile from 'to-vfile';
|
||||
import plugin from '../index';
|
||||
import type {AdmonitionOptions} from '../index';
|
||||
|
||||
const processFixture = async (
|
||||
name: string,
|
||||
options?: Partial<AdmonitionOptions>,
|
||||
) => {
|
||||
const filePath = path.join(__dirname, '__fixtures__', `${name}.md`);
|
||||
const file = await vfile.read(filePath);
|
||||
|
||||
const result = await remark()
|
||||
.use(plugin, options)
|
||||
.use(remark2rehype)
|
||||
.use(stringify)
|
||||
.process(file);
|
||||
|
||||
return result.toString();
|
||||
};
|
||||
|
||||
describe('admonitions remark plugin', () => {
|
||||
it('base', async () => {
|
||||
const result = await processFixture('base');
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('custom keywords', async () => {
|
||||
const result = await processFixture('base', {keywords: ['tip']});
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('custom tag', async () => {
|
||||
const result = await processFixture('base', {tag: '++++'});
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('interpolation', async () => {
|
||||
const result = await processFixture('interpolation');
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
182
packages/docusaurus-mdx-loader/src/remark/admonitions/index.ts
Normal file
182
packages/docusaurus-mdx-loader/src/remark/admonitions/index.ts
Normal file
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* 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, Processor, Plugin} from 'unified';
|
||||
import type {Literal} from 'mdast';
|
||||
|
||||
const NEWLINE = '\n';
|
||||
|
||||
export type AdmonitionOptions = {
|
||||
tag: string;
|
||||
keywords: string[];
|
||||
};
|
||||
|
||||
export const DefaultAdmonitionOptions: AdmonitionOptions = {
|
||||
tag: ':::',
|
||||
keywords: [
|
||||
'secondary',
|
||||
'info',
|
||||
'success',
|
||||
'danger',
|
||||
'note',
|
||||
'tip',
|
||||
'warning',
|
||||
'important',
|
||||
'caution',
|
||||
],
|
||||
};
|
||||
|
||||
function escapeRegExp(s: string): string {
|
||||
return s.replace(/[-[\]{}()*+?.\\^$|/]/g, '\\$&');
|
||||
}
|
||||
|
||||
function normalizeOptions(
|
||||
options: Partial<AdmonitionOptions>,
|
||||
): AdmonitionOptions {
|
||||
return {...DefaultAdmonitionOptions, ...options};
|
||||
}
|
||||
|
||||
// This string value does not matter much
|
||||
// It is ignored because nodes are using hName/hProperties coming from HAST
|
||||
const admonitionNodeType = 'admonitionHTML';
|
||||
|
||||
const plugin: Plugin = function plugin(
|
||||
this: Processor,
|
||||
optionsInput: Partial<AdmonitionOptions> = {},
|
||||
): Transformer {
|
||||
const options = normalizeOptions(optionsInput);
|
||||
|
||||
const keywords = Object.values(options.keywords).map(escapeRegExp).join('|');
|
||||
const tag = escapeRegExp(options.tag);
|
||||
const regex = new RegExp(`${tag}(${keywords})(?: *(.*))?\n`);
|
||||
const escapeTag = new RegExp(escapeRegExp(`\\${options.tag}`), 'g');
|
||||
|
||||
// The tokenizer is called on blocks to determine if there is an admonition
|
||||
// present and create tags for it
|
||||
function blockTokenizer(this: any, eat: any, value: string, silent: boolean) {
|
||||
// Stop if no match or match does not start at beginning of line
|
||||
const match = regex.exec(value);
|
||||
if (!match || match.index !== 0) {
|
||||
return false;
|
||||
}
|
||||
// If silent return the match
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const now = eat.now();
|
||||
const [opening, keyword, title] = match;
|
||||
const food = [];
|
||||
const content = [];
|
||||
|
||||
let newValue = value;
|
||||
// consume lines until a closing tag
|
||||
let idx = newValue.indexOf(NEWLINE);
|
||||
while (idx !== -1) {
|
||||
// grab this line and eat it
|
||||
const next = newValue.indexOf(NEWLINE, idx + 1);
|
||||
const line =
|
||||
next !== -1 ? newValue.slice(idx + 1, next) : newValue.slice(idx + 1);
|
||||
food.push(line);
|
||||
newValue = newValue.slice(idx + 1);
|
||||
// the closing tag is NOT part of the content
|
||||
if (line.startsWith(options.tag)) {
|
||||
break;
|
||||
}
|
||||
content.push(line);
|
||||
idx = newValue.indexOf(NEWLINE);
|
||||
}
|
||||
|
||||
// consume the processed tag and replace escape sequences
|
||||
const contentString = content.join(NEWLINE).replace(escapeTag, options.tag);
|
||||
const add = eat(opening + food.join(NEWLINE));
|
||||
|
||||
// parse the content in block mode
|
||||
const exit = this.enterBlock();
|
||||
const contentNodes = this.tokenizeBlock(contentString, now);
|
||||
exit();
|
||||
|
||||
const titleNodes = this.tokenizeInline(title, now);
|
||||
|
||||
const isSimpleTextTitle =
|
||||
titleNodes.length === 1 && titleNodes[0].type === 'text';
|
||||
|
||||
const element = {
|
||||
type: admonitionNodeType,
|
||||
data: {
|
||||
// hName/hProperties come from HAST
|
||||
// See https://github.com/syntax-tree/mdast-util-to-hast#fields-on-nodes
|
||||
hName: 'admonition',
|
||||
hProperties: {
|
||||
...(title && isSimpleTextTitle && {title}),
|
||||
type: keyword,
|
||||
},
|
||||
},
|
||||
children: [
|
||||
// For titles containing MDX syntax: create a custom element. The theme
|
||||
// component will extract it and render it nicely.
|
||||
//
|
||||
// Temporary workaround, because it's complex in MDX v1 to emit
|
||||
// interpolated JSX prop syntax (title={<>my <code>title</code></>}).
|
||||
// For this reason, we use children instead of the title prop.
|
||||
title &&
|
||||
!isSimpleTextTitle && {
|
||||
type: admonitionNodeType,
|
||||
data: {
|
||||
hName: 'mdxAdmonitionTitle',
|
||||
hProperties: {},
|
||||
},
|
||||
children: titleNodes,
|
||||
},
|
||||
...contentNodes,
|
||||
].filter(Boolean),
|
||||
};
|
||||
|
||||
return add(element);
|
||||
}
|
||||
|
||||
// add tokenizer to parser after fenced code blocks
|
||||
const Parser = this.Parser.prototype;
|
||||
Parser.blockTokenizers.admonition = blockTokenizer;
|
||||
Parser.blockMethods.splice(
|
||||
Parser.blockMethods.indexOf('fencedCode') + 1,
|
||||
0,
|
||||
'admonition',
|
||||
);
|
||||
Parser.interruptParagraph.splice(
|
||||
Parser.interruptParagraph.indexOf('fencedCode') + 1,
|
||||
0,
|
||||
['admonition'],
|
||||
);
|
||||
Parser.interruptList.splice(
|
||||
Parser.interruptList.indexOf('fencedCode') + 1,
|
||||
0,
|
||||
['admonition'],
|
||||
);
|
||||
Parser.interruptBlockquote.splice(
|
||||
Parser.interruptBlockquote.indexOf('fencedCode') + 1,
|
||||
0,
|
||||
['admonition'],
|
||||
);
|
||||
|
||||
return (root) => {
|
||||
// escape everything except admonitionHTML nodes
|
||||
visit(
|
||||
root,
|
||||
(node: unknown): node is Literal =>
|
||||
(node as Literal)?.type !== admonitionNodeType,
|
||||
(node: Literal) => {
|
||||
if (node.value) {
|
||||
node.value = node.value.replace(escapeTag, options.tag);
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
export default plugin;
|
|
@ -30,7 +30,6 @@
|
|||
"fs-extra": "^10.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"reading-time": "^1.5.0",
|
||||
"remark-admonitions": "^1.2.1",
|
||||
"tslib": "^2.4.0",
|
||||
"unist-util-visit": "^2.0.3",
|
||||
"utility-types": "^3.10.0",
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare module 'remark-admonitions' {
|
||||
type Options = {[key: string]: unknown};
|
||||
|
||||
const plugin: (options?: Options) => void;
|
||||
export = plugin;
|
||||
}
|
|
@ -21,7 +21,6 @@ import {
|
|||
type TagsListItem,
|
||||
type TagModule,
|
||||
} from '@docusaurus/utils';
|
||||
import admonitions from 'remark-admonitions';
|
||||
import {
|
||||
generateBlogPosts,
|
||||
getSourceToPermalink,
|
||||
|
@ -49,12 +48,6 @@ export default async function pluginContentBlog(
|
|||
context: LoadContext,
|
||||
options: PluginOptions,
|
||||
): Promise<Plugin<BlogContent>> {
|
||||
if (options.admonitions) {
|
||||
options.remarkPlugins = options.remarkPlugins.concat([
|
||||
[admonitions, options.admonitions],
|
||||
]);
|
||||
}
|
||||
|
||||
const {
|
||||
siteDir,
|
||||
siteConfig,
|
||||
|
@ -381,6 +374,7 @@ export default async function pluginContentBlog(
|
|||
|
||||
configureWebpack(_config, isServer, {getJSLoader}, content) {
|
||||
const {
|
||||
admonitions,
|
||||
rehypePlugins,
|
||||
remarkPlugins,
|
||||
truncateMarker,
|
||||
|
@ -423,6 +417,7 @@ export default async function pluginContentBlog(
|
|||
{
|
||||
loader: require.resolve('@docusaurus/mdx-loader'),
|
||||
options: {
|
||||
admonitions,
|
||||
remarkPlugins,
|
||||
rehypePlugins,
|
||||
beforeDefaultRemarkPlugins: [
|
||||
|
|
|
@ -24,7 +24,7 @@ export const DEFAULT_OPTIONS: PluginOptions = {
|
|||
feedOptions: {type: ['rss', 'atom'], copyright: ''},
|
||||
beforeDefaultRehypePlugins: [],
|
||||
beforeDefaultRemarkPlugins: [],
|
||||
admonitions: {},
|
||||
admonitions: true,
|
||||
truncateMarker: /<!--\s*truncate\s*-->/,
|
||||
rehypePlugins: [],
|
||||
remarkPlugins: [],
|
||||
|
|
|
@ -377,7 +377,6 @@ declare module '@docusaurus/plugin-content-blog' {
|
|||
* unlocalized file. Ignored when `editUrl` is a function.
|
||||
*/
|
||||
editLocalizedFiles?: boolean;
|
||||
admonitions: {[key: string]: unknown};
|
||||
/** Path to the authors map file, relative to the blog content directory. */
|
||||
authorsMapPath: string;
|
||||
/** A callback to customize the reading time number displayed. */
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
"import-fresh": "^3.3.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"remark-admonitions": "^1.2.1",
|
||||
"tslib": "^2.4.0",
|
||||
"utility-types": "^3.10.0",
|
||||
"webpack": "^5.72.1"
|
||||
|
|
|
@ -63,7 +63,7 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
breadcrumbs: true,
|
||||
showLastUpdateTime: true,
|
||||
showLastUpdateAuthor: true,
|
||||
admonitions: {},
|
||||
admonitions: false,
|
||||
includeCurrentVersion: false,
|
||||
disableVersioning: true,
|
||||
editCurrentVersion: true,
|
||||
|
@ -84,7 +84,6 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
expect(testValidate(userOptions)).toEqual({
|
||||
...defaultOptions,
|
||||
...userOptions,
|
||||
remarkPlugins: [...userOptions.remarkPlugins!, expect.any(Array)],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -102,7 +101,6 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
expect(testValidate(userOptions)).toEqual({
|
||||
...defaultOptions,
|
||||
...userOptions,
|
||||
remarkPlugins: [...userOptions.remarkPlugins!, expect.any(Array)],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -116,14 +114,14 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('rejects admonitions true', () => {
|
||||
const admonitionsTrue: Options = {
|
||||
admonitions: true,
|
||||
};
|
||||
it('rejects admonitions array', () => {
|
||||
expect(() =>
|
||||
testValidate(admonitionsTrue),
|
||||
testValidate({
|
||||
// @ts-expect-error: rejected value
|
||||
admonitions: [],
|
||||
}),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`""admonitions" contains an invalid value"`,
|
||||
`""admonitions" does not look like a valid admonitions config"`,
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare module 'remark-admonitions' {
|
||||
type Options = {[key: string]: unknown};
|
||||
|
||||
const plugin: (options?: Options) => void;
|
||||
export = plugin;
|
||||
}
|
|
@ -352,6 +352,7 @@ export default async function pluginContentDocs(
|
|||
{
|
||||
loader: require.resolve('@docusaurus/mdx-loader'),
|
||||
options: {
|
||||
admonitions: options.admonitions,
|
||||
remarkPlugins,
|
||||
rehypePlugins,
|
||||
beforeDefaultRehypePlugins,
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
URISchema,
|
||||
} from '@docusaurus/utils-validation';
|
||||
import {GlobExcludeDefault} from '@docusaurus/utils';
|
||||
import admonitions from 'remark-admonitions';
|
||||
import {DefaultSidebarItemsGenerator} from './sidebars/generator';
|
||||
import {
|
||||
DefaultNumberPrefixParser,
|
||||
|
@ -42,7 +41,7 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
|
|||
beforeDefaultRehypePlugins: [],
|
||||
showLastUpdateTime: false,
|
||||
showLastUpdateAuthor: false,
|
||||
admonitions: {},
|
||||
admonitions: true,
|
||||
includeCurrentVersion: true,
|
||||
disableVersioning: false,
|
||||
lastVersion: undefined,
|
||||
|
@ -123,9 +122,7 @@ const OptionsSchema = Joi.object<PluginOptions>({
|
|||
beforeDefaultRehypePlugins: RehypePluginsSchema.default(
|
||||
DEFAULT_OPTIONS.beforeDefaultRehypePlugins,
|
||||
),
|
||||
admonitions: Joi.alternatives()
|
||||
.try(AdmonitionsSchema, Joi.boolean().invalid(true))
|
||||
.default(DEFAULT_OPTIONS.admonitions),
|
||||
admonitions: AdmonitionsSchema.default(DEFAULT_OPTIONS.admonitions),
|
||||
showLastUpdateTime: Joi.bool().default(DEFAULT_OPTIONS.showLastUpdateTime),
|
||||
showLastUpdateAuthor: Joi.bool().default(
|
||||
DEFAULT_OPTIONS.showLastUpdateAuthor,
|
||||
|
@ -167,11 +164,5 @@ export function validateOptions({
|
|||
|
||||
const normalizedOptions = validate(OptionsSchema, options);
|
||||
|
||||
if (normalizedOptions.admonitions) {
|
||||
normalizedOptions.remarkPlugins = normalizedOptions.remarkPlugins.concat([
|
||||
[admonitions, normalizedOptions.admonitions],
|
||||
]);
|
||||
}
|
||||
|
||||
return normalizedOptions;
|
||||
}
|
||||
|
|
|
@ -206,7 +206,6 @@ declare module '@docusaurus/plugin-content-docs' {
|
|||
docTagsListComponent: string;
|
||||
/** Root component of the generated category index page. */
|
||||
docCategoryGeneratedIndexComponent: string;
|
||||
admonitions: {[key: string]: unknown};
|
||||
sidebarItemsGenerator: import('./sidebars/types').SidebarItemsGeneratorOption;
|
||||
/**
|
||||
* URL route for the tags section of your doc version. Will be appended to
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
"@docusaurus/utils": "2.0.0-beta.21",
|
||||
"@docusaurus/utils-validation": "2.0.0-beta.21",
|
||||
"fs-extra": "^10.1.0",
|
||||
"remark-admonitions": "^1.2.1",
|
||||
"tslib": "^2.4.0",
|
||||
"webpack": "^5.72.1"
|
||||
},
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare module 'remark-admonitions' {
|
||||
type Options = {[key: string]: unknown};
|
||||
|
||||
const plugin: (options?: Options) => void;
|
||||
export = plugin;
|
||||
}
|
|
@ -21,7 +21,6 @@ import {
|
|||
DEFAULT_PLUGIN_ID,
|
||||
parseMarkdownString,
|
||||
} from '@docusaurus/utils';
|
||||
import admonitions from 'remark-admonitions';
|
||||
import {validatePageFrontMatter} from './frontMatter';
|
||||
|
||||
import type {LoadContext, Plugin} from '@docusaurus/types';
|
||||
|
@ -43,11 +42,6 @@ export default function pluginContentPages(
|
|||
context: LoadContext,
|
||||
options: PluginOptions,
|
||||
): Plugin<LoadedContent | null> {
|
||||
if (options.admonitions) {
|
||||
options.remarkPlugins = options.remarkPlugins.concat([
|
||||
[admonitions, options.admonitions],
|
||||
]);
|
||||
}
|
||||
const {siteConfig, siteDir, generatedFilesDir, localizationDir} = context;
|
||||
|
||||
const contentPaths: PagesContentPaths = {
|
||||
|
@ -170,6 +164,7 @@ export default function pluginContentPages(
|
|||
|
||||
configureWebpack(config, isServer, {getJSLoader}) {
|
||||
const {
|
||||
admonitions,
|
||||
rehypePlugins,
|
||||
remarkPlugins,
|
||||
beforeDefaultRehypePlugins,
|
||||
|
@ -194,6 +189,7 @@ export default function pluginContentPages(
|
|||
{
|
||||
loader: require.resolve('@docusaurus/mdx-loader'),
|
||||
options: {
|
||||
admonitions,
|
||||
remarkPlugins,
|
||||
rehypePlugins,
|
||||
beforeDefaultRehypePlugins,
|
||||
|
|
|
@ -25,7 +25,7 @@ export const DEFAULT_OPTIONS: PluginOptions = {
|
|||
rehypePlugins: [],
|
||||
beforeDefaultRehypePlugins: [],
|
||||
beforeDefaultRemarkPlugins: [],
|
||||
admonitions: {},
|
||||
admonitions: true,
|
||||
};
|
||||
|
||||
const PluginOptionSchema = Joi.object<PluginOptions>({
|
||||
|
|
|
@ -16,7 +16,6 @@ declare module '@docusaurus/plugin-content-pages' {
|
|||
include: string[];
|
||||
exclude: string[];
|
||||
mdxPageComponent: string;
|
||||
admonitions: {[key: string]: unknown};
|
||||
};
|
||||
|
||||
export type Options = Partial<PluginOptions>;
|
||||
|
|
|
@ -139,7 +139,6 @@ export default function themeClassic(
|
|||
const modules = [
|
||||
require.resolve(getInfimaCSSFile(direction)),
|
||||
'./prism-include-languages',
|
||||
'./admonitions.css',
|
||||
'./nprogress',
|
||||
];
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ declare module '@theme/Admonition' {
|
|||
readonly children: ReactNode;
|
||||
readonly type: 'note' | 'tip' | 'danger' | 'info' | 'caution';
|
||||
readonly icon?: ReactNode;
|
||||
readonly title?: string;
|
||||
readonly title?: ReactNode;
|
||||
}
|
||||
export default function Admonition(props: Props): JSX.Element;
|
||||
}
|
||||
|
@ -675,6 +675,7 @@ declare module '@theme/MDXComponents' {
|
|||
import type MDXDetails from '@theme/MDXComponents/Details';
|
||||
import type MDXUl from '@theme/MDXComponents/Ul';
|
||||
import type MDXImg from '@theme/MDXComponents/Img';
|
||||
import type Admonition from '@theme/Admonition';
|
||||
|
||||
export type MDXComponentsObject = {
|
||||
readonly head: typeof MDXHead;
|
||||
|
@ -690,6 +691,7 @@ declare module '@theme/MDXComponents' {
|
|||
readonly h4: (props: ComponentProps<'h4'>) => JSX.Element;
|
||||
readonly h5: (props: ComponentProps<'h5'>) => JSX.Element;
|
||||
readonly h6: (props: ComponentProps<'h6'>) => JSX.Element;
|
||||
readonly admonition: typeof Admonition;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[tagName: string]: ComponentType<any>;
|
||||
};
|
||||
|
|
|
@ -5,102 +5,161 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {type ReactNode} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import type {Props} from '@theme/Admonition';
|
||||
|
||||
const icons = {
|
||||
note: (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14"
|
||||
height="16"
|
||||
viewBox="0 0 14 16">
|
||||
import styles from './styles.module.css';
|
||||
|
||||
function NoteIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 14 16">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
tip: (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="12"
|
||||
height="16"
|
||||
viewBox="0 0 12 16">
|
||||
);
|
||||
}
|
||||
|
||||
function TipIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 12 16">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
danger: (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="12"
|
||||
height="16"
|
||||
viewBox="0 0 12 16">
|
||||
);
|
||||
}
|
||||
|
||||
function DangerIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 12 16">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
info: (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14"
|
||||
height="16"
|
||||
viewBox="0 0 14 16">
|
||||
);
|
||||
}
|
||||
|
||||
function InfoIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 14 16">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
caution: (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16">
|
||||
);
|
||||
}
|
||||
|
||||
function CautionIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 16 16">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
type AdmonitionConfig = {
|
||||
iconComponent: React.ComponentType;
|
||||
infimaClassName: string;
|
||||
};
|
||||
|
||||
const ifmClassNames = {
|
||||
note: 'secondary',
|
||||
tip: 'success',
|
||||
danger: 'danger',
|
||||
info: 'info',
|
||||
caution: 'warning',
|
||||
const AdmonitionConfigs: {[key: string]: AdmonitionConfig | string} = {
|
||||
note: {
|
||||
infimaClassName: 'secondary',
|
||||
iconComponent: NoteIcon,
|
||||
},
|
||||
tip: {
|
||||
infimaClassName: 'success',
|
||||
iconComponent: TipIcon,
|
||||
},
|
||||
danger: {
|
||||
infimaClassName: 'danger',
|
||||
iconComponent: DangerIcon,
|
||||
},
|
||||
info: {
|
||||
infimaClassName: 'info',
|
||||
iconComponent: InfoIcon,
|
||||
},
|
||||
caution: {
|
||||
infimaClassName: 'warning',
|
||||
iconComponent: CautionIcon,
|
||||
},
|
||||
secondary: 'note',
|
||||
important: 'info',
|
||||
success: 'tip',
|
||||
warning: 'danger',
|
||||
};
|
||||
|
||||
export default function Admonition({
|
||||
children,
|
||||
type,
|
||||
title = type,
|
||||
icon = icons[type],
|
||||
}: Props): JSX.Element {
|
||||
function getAdmonitionConfig(type: string): AdmonitionConfig {
|
||||
const config = AdmonitionConfigs[type];
|
||||
if (config) {
|
||||
if (typeof config === 'string') {
|
||||
return AdmonitionConfigs[config] as AdmonitionConfig;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
console.warn(
|
||||
`No admonition config found for admonition type "${type}". Using Info as fallback.`,
|
||||
);
|
||||
return AdmonitionConfigs.info as AdmonitionConfig;
|
||||
}
|
||||
|
||||
// Workaround because it's difficult in MDX v1 to provide a MDX title as props
|
||||
// See https://github.com/facebook/docusaurus/pull/7152#issuecomment-1145779682
|
||||
function extractMDXAdmonitionTitle(children: ReactNode): {
|
||||
mdxAdmonitionTitle: ReactNode | undefined;
|
||||
rest: ReactNode;
|
||||
} {
|
||||
const items = React.Children.toArray(children);
|
||||
const mdxAdmonitionTitle = items.find(
|
||||
(item) =>
|
||||
React.isValidElement(item) &&
|
||||
(item.props as {mdxType: string} | null)?.mdxType ===
|
||||
'mdxAdmonitionTitle',
|
||||
);
|
||||
const rest = <>{items.filter((item) => item !== mdxAdmonitionTitle)}</>;
|
||||
return {
|
||||
mdxAdmonitionTitle,
|
||||
rest,
|
||||
};
|
||||
}
|
||||
|
||||
function processAdmonitionProps(props: Props): Props {
|
||||
const {mdxAdmonitionTitle, rest} = extractMDXAdmonitionTitle(props.children);
|
||||
return {
|
||||
...props,
|
||||
title: props.title ?? mdxAdmonitionTitle ?? props.type,
|
||||
children: rest,
|
||||
};
|
||||
}
|
||||
|
||||
export default function Admonition(props: Props): JSX.Element {
|
||||
const {
|
||||
children,
|
||||
type,
|
||||
title = type,
|
||||
icon: iconProp,
|
||||
} = processAdmonitionProps(props);
|
||||
|
||||
const config = getAdmonitionConfig(type);
|
||||
const {infimaClassName, iconComponent: IconComponent} = config;
|
||||
const icon = iconProp ?? <IconComponent />;
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'admonition',
|
||||
`admonition-${type}`,
|
||||
'alert',
|
||||
`alert--${ifmClassNames[type]}`,
|
||||
)}>
|
||||
<div className="admonition-heading">
|
||||
<h5>
|
||||
<span className="admonition-icon">{icon}</span>
|
||||
{title}
|
||||
</h5>
|
||||
className={clsx('alert', `alert--${infimaClassName}`, styles.admonition)}>
|
||||
<div className={styles.admonitionHeading}>
|
||||
<span className={styles.admonitionIcon}>{icon}</span>
|
||||
{title}
|
||||
</div>
|
||||
<div className="admonition-content">{children}</div>
|
||||
<div className={styles.admonitionContent}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,35 +5,34 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.admonition h5 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 8px;
|
||||
text-transform: uppercase;
|
||||
.admonition {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.admonition h5 code {
|
||||
.admonitionHeading {
|
||||
font: var(--ifm-heading-font-weight) var(--ifm-h5-font-size) /
|
||||
var(--ifm-heading-line-height) var(--ifm-heading-font-family);
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.admonitionHeading code {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.admonition-icon {
|
||||
.admonitionIcon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: 0.4em;
|
||||
}
|
||||
|
||||
.admonition-icon svg {
|
||||
.admonitionIcon svg {
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
stroke-width: 0;
|
||||
height: 1.6em;
|
||||
width: 1.6em;
|
||||
fill: var(--ifm-alert-foreground-color);
|
||||
stroke: var(--ifm-alert-foreground-color);
|
||||
}
|
||||
|
||||
.admonition-content > :last-child {
|
||||
.admonitionContent > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.admonition {
|
||||
margin-bottom: 1em;
|
||||
}
|
|
@ -14,6 +14,7 @@ import MDXDetails from '@theme/MDXComponents/Details';
|
|||
import MDXHeading from '@theme/MDXComponents/Heading';
|
||||
import MDXUl from '@theme/MDXComponents/Ul';
|
||||
import MDXImg from '@theme/MDXComponents/Img';
|
||||
import Admonition from '@theme/Admonition';
|
||||
|
||||
import type {MDXComponentsObject} from '@theme/MDXComponents';
|
||||
|
||||
|
@ -31,6 +32,7 @@ const MDXComponents: MDXComponentsObject = {
|
|||
h4: (props) => <MDXHeading as="h4" {...props} />,
|
||||
h5: (props) => <MDXHeading as="h5" {...props} />,
|
||||
h6: (props) => <MDXHeading as="h6" {...props} />,
|
||||
admonition: Admonition,
|
||||
};
|
||||
|
||||
export default MDXComponents;
|
||||
|
|
|
@ -1,12 +1,32 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`validation schemas admonitionsSchema: for value=[] 1`] = `""value" must be of type object"`;
|
||||
exports[`validation schemas admonitionsSchema: for value=[] 1`] = `""value" does not look like a valid admonitions config"`;
|
||||
|
||||
exports[`validation schemas admonitionsSchema: for value=3 1`] = `""value" must be of type object"`;
|
||||
exports[`validation schemas admonitionsSchema: for value={"customTypes":{"myKeyword":{"keyword":"myKeyword","infima":true,"svg":"<svg width=\\"512px\\" height=\\"512px\\" viewBox=\\"0 0 512 512\\" xmlns=\\"http://www.w3.org/2000/svg\\"></svg>"}}} 1`] = `
|
||||
"The Docusaurus admonitions system has changed, and the option "customTypes" does not exist anymore.
|
||||
You now need to swizzle the admonitions component to provide UI customizations such as icons.
|
||||
Please refer to https://github.com/facebook/docusaurus/pull/7152 for detailed upgrade instructions."
|
||||
`;
|
||||
|
||||
exports[`validation schemas admonitionsSchema: for value=null 1`] = `""value" must be of type object"`;
|
||||
exports[`validation schemas admonitionsSchema: for value={"icons":"emoji"} 1`] = `
|
||||
"The Docusaurus admonitions system has changed, and the option "icons" does not exist anymore.
|
||||
You now need to swizzle the admonitions component to provide UI customizations such as icons.
|
||||
Please refer to https://github.com/facebook/docusaurus/pull/7152 for detailed upgrade instructions."
|
||||
`;
|
||||
|
||||
exports[`validation schemas admonitionsSchema: for value=true 1`] = `""value" must be of type object"`;
|
||||
exports[`validation schemas admonitionsSchema: for value={"infima":true} 1`] = `
|
||||
"The Docusaurus admonitions system has changed, and the option "infima" does not exist anymore.
|
||||
You now need to swizzle the admonitions component to provide UI customizations such as icons.
|
||||
Please refer to https://github.com/facebook/docusaurus/pull/7152 for detailed upgrade instructions."
|
||||
`;
|
||||
|
||||
exports[`validation schemas admonitionsSchema: for value={"keywords":[]} 1`] = `""keywords" does not contain 1 required value(s)"`;
|
||||
|
||||
exports[`validation schemas admonitionsSchema: for value={"tag":""} 1`] = `""tag" is not allowed to be empty"`;
|
||||
|
||||
exports[`validation schemas admonitionsSchema: for value={"unknownAttribute":"val"} 1`] = `""unknownAttribute" is not allowed"`;
|
||||
|
||||
exports[`validation schemas admonitionsSchema: for value=3 1`] = `""value" does not look like a valid admonitions config"`;
|
||||
|
||||
exports[`validation schemas pathnameSchema: for value="foo" 1`] = `""value" is not a valid pathname. Pathname should start with slash and not contain any domain or query string."`;
|
||||
|
||||
|
|
|
@ -87,17 +87,39 @@ describe('validation schemas', () => {
|
|||
it('admonitionsSchema', () => {
|
||||
const {testOK, testFail} = createTestHelpers({
|
||||
schema: AdmonitionsSchema,
|
||||
defaultValue: {},
|
||||
defaultValue: true,
|
||||
});
|
||||
|
||||
testOK(undefined);
|
||||
testOK(true);
|
||||
testOK(false);
|
||||
testOK({});
|
||||
testOK({attr: 'val'});
|
||||
testOK({tag: '+++'});
|
||||
testOK({keywords: ['info', 'tip']});
|
||||
testOK({tag: '+++', keywords: ['info', 'tip']});
|
||||
|
||||
testFail(null);
|
||||
testFail(3);
|
||||
testFail(true);
|
||||
testFail([]);
|
||||
testFail({unknownAttribute: 'val'});
|
||||
testFail({tag: ''});
|
||||
testFail({keywords: []});
|
||||
|
||||
// Legacy types
|
||||
testFail({
|
||||
infima: true,
|
||||
});
|
||||
testFail({
|
||||
icons: 'emoji',
|
||||
});
|
||||
testFail({
|
||||
customTypes: {
|
||||
myKeyword: {
|
||||
keyword: `myKeyword`,
|
||||
infima: true,
|
||||
svg: '<svg width="512px" height="512px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"></svg>',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('remarkPluginsSchema', () => {
|
||||
|
|
|
@ -32,7 +32,31 @@ const MarkdownPluginsSchema = Joi.array()
|
|||
export const RemarkPluginsSchema = MarkdownPluginsSchema;
|
||||
export const RehypePluginsSchema = MarkdownPluginsSchema;
|
||||
|
||||
export const AdmonitionsSchema = Joi.object().default({});
|
||||
const LegacyAdmonitionConfigSchema = Joi.forbidden().messages({
|
||||
'any.unknown': `The Docusaurus admonitions system has changed, and the option {#label} does not exist anymore.
|
||||
You now need to swizzle the admonitions component to provide UI customizations such as icons.
|
||||
Please refer to https://github.com/facebook/docusaurus/pull/7152 for detailed upgrade instructions.`,
|
||||
});
|
||||
|
||||
export const AdmonitionsSchema = JoiFrontMatter.alternatives()
|
||||
.try(
|
||||
JoiFrontMatter.boolean().required(),
|
||||
JoiFrontMatter.object({
|
||||
tag: JoiFrontMatter.string(),
|
||||
keywords: JoiFrontMatter.array().items(
|
||||
JoiFrontMatter.string().required(),
|
||||
),
|
||||
// TODO Remove before 2023
|
||||
customTypes: LegacyAdmonitionConfigSchema,
|
||||
icons: LegacyAdmonitionConfigSchema,
|
||||
infima: LegacyAdmonitionConfigSchema,
|
||||
}).required(),
|
||||
)
|
||||
.default(true)
|
||||
.messages({
|
||||
'alternatives.types':
|
||||
'{{#label}} does not look like a valid admonitions config',
|
||||
});
|
||||
|
||||
// TODO how can we make this emit a custom error message :'(
|
||||
// Joi is such a pain, good luck to annoying trying to improve this
|
||||
|
|
|
@ -90,7 +90,6 @@
|
|||
"react-router": "^5.3.3",
|
||||
"react-router-config": "^5.1.1",
|
||||
"react-router-dom": "^5.3.3",
|
||||
"remark-admonitions": "^1.2.1",
|
||||
"rtl-detect": "^1.0.4",
|
||||
"semver": "^7.3.7",
|
||||
"serve-handler": "^6.1.3",
|
||||
|
|
2
packages/docusaurus/src/deps.d.ts
vendored
2
packages/docusaurus/src/deps.d.ts
vendored
|
@ -5,8 +5,6 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
declare module 'remark-admonitions';
|
||||
|
||||
declare module 'react-loadable-ssr-addon-v5-slorber' {
|
||||
import type {WebpackPluginInstance, Compiler} from 'webpack';
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import path from 'path';
|
||||
import admonitions from 'remark-admonitions';
|
||||
import type {RuleSetRule} from 'webpack';
|
||||
import type {HtmlTagObject, LoadedPlugin, LoadContext} from '@docusaurus/types';
|
||||
|
||||
|
@ -97,6 +96,7 @@ export function createMDXFallbackPlugin({
|
|||
});
|
||||
}
|
||||
const mdxLoaderOptions = {
|
||||
admonitions: true,
|
||||
staticDirs: siteConfig.staticDirectories.map((dir) =>
|
||||
path.resolve(siteDir, dir),
|
||||
),
|
||||
|
@ -105,7 +105,6 @@ export function createMDXFallbackPlugin({
|
|||
isMDXPartial: () => true,
|
||||
// External MDX files might have front matter, just disable the warning
|
||||
isMDXPartialFrontMatterWarningDisabled: true,
|
||||
remarkPlugins: [admonitions],
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -221,3 +221,11 @@ Can be arbitrarily nested:
|
|||
- [ ] Task
|
||||
- [ ] Task
|
||||
- [ ] Task
|
||||
|
||||
## Admonitions
|
||||
|
||||
:::caution Interpolated `title` with a <button style={{color: "red"}} onClick={() => alert("it works")}>button</button>
|
||||
|
||||
Admonition body
|
||||
|
||||
:::
|
||||
|
|
110
yarn.lock
110
yarn.lock
|
@ -5190,7 +5190,7 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001332, caniuse-lite@^1.0.30001335:
|
|||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz#8a1e7fdc4db9c2ec79a05e9fd68eb93a761888bb"
|
||||
integrity sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==
|
||||
|
||||
ccount@^1.0.0, ccount@^1.0.3:
|
||||
ccount@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043"
|
||||
integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==
|
||||
|
@ -8120,17 +8120,6 @@ hast-to-hyperscript@^9.0.0:
|
|||
unist-util-is "^4.0.0"
|
||||
web-namespaces "^1.0.0"
|
||||
|
||||
hast-util-from-parse5@^5.0.0:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz#3089dc0ee2ccf6ec8bc416919b51a54a589e097c"
|
||||
integrity sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==
|
||||
dependencies:
|
||||
ccount "^1.0.3"
|
||||
hastscript "^5.0.0"
|
||||
property-information "^5.0.0"
|
||||
web-namespaces "^1.1.2"
|
||||
xtend "^4.0.1"
|
||||
|
||||
hast-util-from-parse5@^6.0.0:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a"
|
||||
|
@ -8157,6 +8146,11 @@ hast-util-from-parse5@^7.0.0:
|
|||
vfile-location "^4.0.0"
|
||||
web-namespaces "^2.0.0"
|
||||
|
||||
hast-util-is-element@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425"
|
||||
integrity sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==
|
||||
|
||||
hast-util-is-element@^2.0.0:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-2.1.2.tgz#fc0b0dc7cef3895e839b8d66979d57b0338c68f3"
|
||||
|
@ -8193,6 +8187,22 @@ hast-util-raw@6.0.1:
|
|||
xtend "^4.0.0"
|
||||
zwitch "^1.0.0"
|
||||
|
||||
hast-util-to-html@^7.1.1:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-7.1.3.tgz#9f339ca9bea71246e565fc79ff7dbfe98bb50f5e"
|
||||
integrity sha512-yk2+1p3EJTEE9ZEUkgHsUSVhIpCsL/bvT8E5GzmWc+N1Po5gBw+0F8bo7dpxXR0nu0bQVxVZGX2lBGF21CmeDw==
|
||||
dependencies:
|
||||
ccount "^1.0.0"
|
||||
comma-separated-tokens "^1.0.0"
|
||||
hast-util-is-element "^1.0.0"
|
||||
hast-util-whitespace "^1.0.0"
|
||||
html-void-elements "^1.0.0"
|
||||
property-information "^5.0.0"
|
||||
space-separated-tokens "^1.0.0"
|
||||
stringify-entities "^3.0.1"
|
||||
unist-util-is "^4.0.0"
|
||||
xtend "^4.0.0"
|
||||
|
||||
hast-util-to-parse5@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479"
|
||||
|
@ -8218,15 +8228,10 @@ hast-util-to-text@^3.1.0:
|
|||
hast-util-is-element "^2.0.0"
|
||||
unist-util-find-after "^4.0.0"
|
||||
|
||||
hastscript@^5.0.0:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a"
|
||||
integrity sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==
|
||||
dependencies:
|
||||
comma-separated-tokens "^1.0.0"
|
||||
hast-util-parse-selector "^2.0.0"
|
||||
property-information "^5.0.0"
|
||||
space-separated-tokens "^1.0.0"
|
||||
hast-util-whitespace@^1.0.0:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41"
|
||||
integrity sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A==
|
||||
|
||||
hastscript@^6.0.0:
|
||||
version "6.0.0"
|
||||
|
@ -10365,6 +10370,20 @@ mdast-util-to-hast@10.0.1:
|
|||
unist-util-position "^3.0.0"
|
||||
unist-util-visit "^2.0.0"
|
||||
|
||||
mdast-util-to-hast@^10.2.0:
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz#61875526a017d8857b71abc9333942700b2d3604"
|
||||
integrity sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ==
|
||||
dependencies:
|
||||
"@types/mdast" "^3.0.0"
|
||||
"@types/unist" "^2.0.0"
|
||||
mdast-util-definitions "^4.0.0"
|
||||
mdurl "^1.0.0"
|
||||
unist-builder "^2.0.0"
|
||||
unist-util-generated "^1.0.0"
|
||||
unist-util-position "^3.0.0"
|
||||
unist-util-visit "^2.0.0"
|
||||
|
||||
mdast-util-to-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b"
|
||||
|
@ -11562,7 +11581,7 @@ parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1:
|
|||
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
|
||||
integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
|
||||
|
||||
parse5@^5.0.0, parse5@^5.1.1:
|
||||
parse5@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
|
||||
integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
|
||||
|
@ -12920,15 +12939,6 @@ rehype-katex@^6.0.2:
|
|||
unist-util-remove-position "^4.0.0"
|
||||
unist-util-visit "^4.0.0"
|
||||
|
||||
rehype-parse@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.2.tgz#aeb3fdd68085f9f796f1d3137ae2b85a98406964"
|
||||
integrity sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug==
|
||||
dependencies:
|
||||
hast-util-from-parse5 "^5.0.0"
|
||||
parse5 "^5.0.0"
|
||||
xtend "^4.0.0"
|
||||
|
||||
rehype-parse@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-7.0.1.tgz#58900f6702b56767814afc2a9efa2d42b1c90c57"
|
||||
|
@ -12947,20 +12957,18 @@ rehype-parse@^8.0.0:
|
|||
parse5 "^6.0.0"
|
||||
unified "^10.0.0"
|
||||
|
||||
rehype-stringify@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/rehype-stringify/-/rehype-stringify-8.0.0.tgz#9b6afb599bcf3165f10f93fc8548f9a03d2ec2ba"
|
||||
integrity sha512-VkIs18G0pj2xklyllrPSvdShAV36Ff3yE5PUO9u36f6+2qJFnn22Z5gKwBOwgXviux4UC7K+/j13AnZfPICi/g==
|
||||
dependencies:
|
||||
hast-util-to-html "^7.1.1"
|
||||
|
||||
relateurl@^0.2.7:
|
||||
version "0.2.7"
|
||||
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
|
||||
integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==
|
||||
|
||||
remark-admonitions@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/remark-admonitions/-/remark-admonitions-1.2.1.tgz#87caa1a442aa7b4c0cafa04798ed58a342307870"
|
||||
integrity sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow==
|
||||
dependencies:
|
||||
rehype-parse "^6.0.2"
|
||||
unified "^8.4.2"
|
||||
unist-util-visit "^2.0.1"
|
||||
|
||||
remark-emoji@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.2.0.tgz#1c702090a1525da5b80e15a8f963ef2c8236cac7"
|
||||
|
@ -13016,6 +13024,13 @@ remark-parse@8.0.3, remark-parse@^8.0.0, remark-parse@^8.0.2:
|
|||
vfile-location "^3.0.0"
|
||||
xtend "^4.0.1"
|
||||
|
||||
remark-rehype@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-8.1.0.tgz#610509a043484c1e697437fa5eb3fd992617c945"
|
||||
integrity sha512-EbCu9kHgAxKmW1yEYjx3QafMyGY3q8noUbNUI5xyKbaFP89wbhDrKxyIQNukNYthzjNHZu6J7hwFg7hRm1svYA==
|
||||
dependencies:
|
||||
mdast-util-to-hast "^10.2.0"
|
||||
|
||||
remark-squeeze-paragraphs@4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz#76eb0e085295131c84748c8e43810159c5653ead"
|
||||
|
@ -14883,17 +14898,6 @@ unified@^10.0.0:
|
|||
trough "^2.0.0"
|
||||
vfile "^5.0.0"
|
||||
|
||||
unified@^8.4.2:
|
||||
version "8.4.2"
|
||||
resolved "https://registry.yarnpkg.com/unified/-/unified-8.4.2.tgz#13ad58b4a437faa2751a4a4c6a16f680c500fff1"
|
||||
integrity sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==
|
||||
dependencies:
|
||||
bail "^1.0.0"
|
||||
extend "^3.0.0"
|
||||
is-plain-obj "^2.0.0"
|
||||
trough "^1.0.0"
|
||||
vfile "^4.0.0"
|
||||
|
||||
unified@^9.0.0, unified@^9.2.2:
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975"
|
||||
|
@ -15029,7 +15033,7 @@ unist-util-visit-parents@^5.0.0:
|
|||
"@types/unist" "^2.0.0"
|
||||
unist-util-is "^5.0.0"
|
||||
|
||||
unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist-util-visit@^2.0.3:
|
||||
unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c"
|
||||
integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==
|
||||
|
@ -15372,7 +15376,7 @@ wcwidth@^1.0.0:
|
|||
dependencies:
|
||||
defaults "^1.0.3"
|
||||
|
||||
web-namespaces@^1.0.0, web-namespaces@^1.1.2:
|
||||
web-namespaces@^1.0.0:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec"
|
||||
integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue