mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-11 08:07:26 +02:00
refactor(theme): split admonitions, make swizzle easier, better retrocompatibility (#7945)
Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
This commit is contained in:
parent
f1415525c0
commit
6f63ffe0a3
32 changed files with 914 additions and 236 deletions
|
@ -53,7 +53,7 @@ export type MDXPlugin =
|
||||||
[Plugin<any[]>, any] | Plugin<any[]>;
|
[Plugin<any[]>, any] | Plugin<any[]>;
|
||||||
|
|
||||||
export type MDXOptions = {
|
export type MDXOptions = {
|
||||||
admonitions: boolean | AdmonitionOptions;
|
admonitions: boolean | Partial<AdmonitionOptions>;
|
||||||
remarkPlugins: MDXPlugin[];
|
remarkPlugins: MDXPlugin[];
|
||||||
rehypePlugins: MDXPlugin[];
|
rehypePlugins: MDXPlugin[];
|
||||||
beforeDefaultRemarkPlugins: MDXPlugin[];
|
beforeDefaultRemarkPlugins: MDXPlugin[];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`admonitions remark plugin base 1`] = `
|
exports[`admonitions remark plugin add custom keyword 1`] = `
|
||||||
"<p>The blog feature enables you to deploy in no time a full-featured blog.</p>
|
"<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>
|
<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>
|
<h2>Initial setup {#initial-setup}</h2>
|
||||||
|
@ -11,11 +11,9 @@ exports[`admonitions remark plugin base 1`] = `
|
||||||
<p>++++</p>"
|
<p>++++</p>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`admonitions remark plugin custom keywords 1`] = `
|
exports[`admonitions remark plugin base 1`] = `
|
||||||
"<p>The blog feature enables you to deploy in no time a full-featured blog.</p>
|
"<p>The blog feature enables you to deploy in no time a full-featured blog.</p>
|
||||||
<p>:::info Sample Title</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>
|
||||||
<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>
|
<h2>Initial setup {#initial-setup}</h2>
|
||||||
<p>To set up your site's blog, start by creating a <code>blog</code> directory.</p>
|
<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>
|
<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>
|
||||||
|
@ -38,7 +36,33 @@ exports[`admonitions remark plugin custom tag 1`] = `
|
||||||
<admonition type="tip"><p>Admonition with different syntax</p></admonition>"
|
<admonition type="tip"><p>Admonition with different syntax</p></admonition>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`admonitions remark plugin default behavior for custom keyword 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 interpolation 1`] = `
|
exports[`admonitions remark plugin interpolation 1`] = `
|
||||||
"<p>Test admonition with interpolated title/body</p>
|
"<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>"
|
<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>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`admonitions remark plugin replace custom keyword 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>"
|
||||||
|
`;
|
||||||
|
|
|
@ -36,13 +36,34 @@ describe('admonitions remark plugin', () => {
|
||||||
expect(result).toMatchSnapshot();
|
expect(result).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('custom keywords', async () => {
|
it('default behavior for custom keyword', async () => {
|
||||||
const result = await processFixture('base', {keywords: ['tip']});
|
const result = await processFixture('base', {
|
||||||
|
keywords: ['tip'],
|
||||||
|
// extendDefaults: false, // By default we don't extend
|
||||||
|
});
|
||||||
|
expect(result).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('add custom keyword', async () => {
|
||||||
|
const result = await processFixture('base', {
|
||||||
|
keywords: ['tip'],
|
||||||
|
extendDefaults: true,
|
||||||
|
});
|
||||||
|
expect(result).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('replace custom keyword', async () => {
|
||||||
|
const result = await processFixture('base', {
|
||||||
|
keywords: ['tip'],
|
||||||
|
extendDefaults: false,
|
||||||
|
});
|
||||||
expect(result).toMatchSnapshot();
|
expect(result).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('custom tag', async () => {
|
it('custom tag', async () => {
|
||||||
const result = await processFixture('base', {tag: '++++'});
|
const result = await processFixture('base', {
|
||||||
|
tag: '++++',
|
||||||
|
});
|
||||||
expect(result).toMatchSnapshot();
|
expect(result).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,14 @@ import type {Literal} from 'mdast';
|
||||||
|
|
||||||
const NEWLINE = '\n';
|
const NEWLINE = '\n';
|
||||||
|
|
||||||
|
// TODO not ideal option shape
|
||||||
|
// First let upgrade to MDX 2.0
|
||||||
|
// Maybe we'll want to provide different tags for different admonition types?
|
||||||
|
// Also maybe rename "keywords" to "types"?
|
||||||
export type AdmonitionOptions = {
|
export type AdmonitionOptions = {
|
||||||
tag: string;
|
tag: string;
|
||||||
keywords: string[];
|
keywords: string[];
|
||||||
|
extendDefaults: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DefaultAdmonitionOptions: AdmonitionOptions = {
|
export const DefaultAdmonitionOptions: AdmonitionOptions = {
|
||||||
|
@ -29,6 +34,7 @@ export const DefaultAdmonitionOptions: AdmonitionOptions = {
|
||||||
'important',
|
'important',
|
||||||
'caution',
|
'caution',
|
||||||
],
|
],
|
||||||
|
extendDefaults: false, // TODO make it true by default: breaking change
|
||||||
};
|
};
|
||||||
|
|
||||||
function escapeRegExp(s: string): string {
|
function escapeRegExp(s: string): string {
|
||||||
|
@ -36,9 +42,20 @@ function escapeRegExp(s: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeOptions(
|
function normalizeOptions(
|
||||||
options: Partial<AdmonitionOptions>,
|
providedOptions: Partial<AdmonitionOptions>,
|
||||||
): AdmonitionOptions {
|
): AdmonitionOptions {
|
||||||
return {...DefaultAdmonitionOptions, ...options};
|
const options = {...DefaultAdmonitionOptions, ...providedOptions};
|
||||||
|
|
||||||
|
// By default it makes more sense to append keywords to the default ones
|
||||||
|
// Adding custom keywords is more common than disabling existing ones
|
||||||
|
if (options.extendDefaults) {
|
||||||
|
options.keywords = [
|
||||||
|
...DefaultAdmonitionOptions.keywords,
|
||||||
|
...options.keywords,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This string value does not matter much
|
// This string value does not matter much
|
||||||
|
|
|
@ -12,6 +12,113 @@ import type {SwizzleConfig} from '@docusaurus/types';
|
||||||
export default function getSwizzleConfig(): SwizzleConfig {
|
export default function getSwizzleConfig(): SwizzleConfig {
|
||||||
return {
|
return {
|
||||||
components: {
|
components: {
|
||||||
|
'Admonition/Icon': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'forbidden', // Can't wrap a folder
|
||||||
|
},
|
||||||
|
description: 'The folder containing all admonition icons',
|
||||||
|
},
|
||||||
|
'Admonition/Icon/Caution': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The admonition caution icon',
|
||||||
|
},
|
||||||
|
'Admonition/Icon/Danger': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The admonition danger icon',
|
||||||
|
},
|
||||||
|
'Admonition/Icon/Info': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The admonition info icon',
|
||||||
|
},
|
||||||
|
'Admonition/Icon/Note': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The admonition note icon',
|
||||||
|
},
|
||||||
|
'Admonition/Icon/Tip': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The admonition tip icon',
|
||||||
|
},
|
||||||
|
'Admonition/Layout': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The standard admonition layout applied to all default admonition types',
|
||||||
|
},
|
||||||
|
'Admonition/Type': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'forbidden',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The folder containing all the admonition type components.',
|
||||||
|
},
|
||||||
|
'Admonition/Type/Caution': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The component responsible for rendering a :::caution admonition type',
|
||||||
|
},
|
||||||
|
'Admonition/Type/Danger': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The component responsible for rendering a :::danger admonition type',
|
||||||
|
},
|
||||||
|
'Admonition/Type/Info': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The component responsible for rendering a :::info admonition type',
|
||||||
|
},
|
||||||
|
'Admonition/Type/Note': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The component responsible for rendering a :::note admonition type',
|
||||||
|
},
|
||||||
|
'Admonition/Type/Tip': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The component responsible for rendering a :::tip admonition type',
|
||||||
|
},
|
||||||
|
'Admonition/Types': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
// TODO the swizzle CLI should provide a way to wrap such objects
|
||||||
|
wrap: 'forbidden',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The object mapping admonition type to a React component.\nUse it to add custom admonition type components, or replace existing ones.\nCan be ejected or wrapped (only manually, see our documentation).',
|
||||||
|
},
|
||||||
CodeBlock: {
|
CodeBlock: {
|
||||||
actions: {
|
actions: {
|
||||||
eject: 'safe',
|
eject: 'safe',
|
||||||
|
@ -20,6 +127,14 @@ export default function getSwizzleConfig(): SwizzleConfig {
|
||||||
description:
|
description:
|
||||||
'The component used to render multi-line code blocks, generally used in Markdown files.',
|
'The component used to render multi-line code blocks, generally used in Markdown files.',
|
||||||
},
|
},
|
||||||
|
'CodeBlock/Content': {
|
||||||
|
actions: {
|
||||||
|
eject: 'unsafe',
|
||||||
|
wrap: 'forbidden',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The folder containing components responsible for rendering different types of CodeBlock content.',
|
||||||
|
},
|
||||||
ColorModeToggle: {
|
ColorModeToggle: {
|
||||||
actions: {
|
actions: {
|
||||||
eject: 'safe',
|
eject: 'safe',
|
||||||
|
@ -36,6 +151,17 @@ export default function getSwizzleConfig(): SwizzleConfig {
|
||||||
description:
|
description:
|
||||||
'The component responsible for rendering a list of sidebar items cards.\nNotable used on the category generated-index pages.',
|
'The component responsible for rendering a list of sidebar items cards.\nNotable used on the category generated-index pages.',
|
||||||
},
|
},
|
||||||
|
'DocItem/TOC': {
|
||||||
|
actions: {
|
||||||
|
// Forbidden because it's a parent folder, makes the CLI crash atm
|
||||||
|
// TODO the CLI should rather support --eject
|
||||||
|
// Subfolders can be swizzled
|
||||||
|
eject: 'forbidden',
|
||||||
|
wrap: 'forbidden',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The DocItem TOC is not directly swizzle-able, but you can swizzle its sub-components.',
|
||||||
|
},
|
||||||
DocSidebar: {
|
DocSidebar: {
|
||||||
actions: {
|
actions: {
|
||||||
eject: 'unsafe', // Too much technical code in sidebar, not very safe atm
|
eject: 'unsafe', // Too much technical code in sidebar, not very safe atm
|
||||||
|
@ -101,6 +227,17 @@ export default function getSwizzleConfig(): SwizzleConfig {
|
||||||
},
|
},
|
||||||
description: 'The footer logo',
|
description: 'The footer logo',
|
||||||
},
|
},
|
||||||
|
Icon: {
|
||||||
|
actions: {
|
||||||
|
// Forbidden because it's a parent folder, makes the CLI crash atm
|
||||||
|
// TODO the CLI should rather support --eject
|
||||||
|
// Subfolders can be swizzled
|
||||||
|
eject: 'forbidden',
|
||||||
|
wrap: 'forbidden',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The Icon folder is not directly swizzle-able, but you can swizzle its sub-components.',
|
||||||
|
},
|
||||||
'Icon/Arrow': {
|
'Icon/Arrow': {
|
||||||
actions: {
|
actions: {
|
||||||
eject: 'safe',
|
eject: 'safe',
|
||||||
|
@ -220,7 +357,7 @@ export default function getSwizzleConfig(): SwizzleConfig {
|
||||||
wrap: 'forbidden',
|
wrap: 'forbidden',
|
||||||
},
|
},
|
||||||
description:
|
description:
|
||||||
'The Navbar item components mapping. Can be ejected to add custom navbar item types. See https://github.com/facebook/docusaurus/issues/7227.',
|
'The Navbar item components mapping. Can be ejected to add custom navbar item types.\nSee https://github.com/facebook/docusaurus/issues/7227.',
|
||||||
},
|
},
|
||||||
NotFound: {
|
NotFound: {
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -44,13 +44,114 @@ declare module '@theme/Admonition' {
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
readonly children: ReactNode;
|
readonly children: ReactNode;
|
||||||
readonly type: 'note' | 'tip' | 'danger' | 'info' | 'caution';
|
readonly type: string;
|
||||||
readonly icon?: ReactNode;
|
readonly icon?: ReactNode;
|
||||||
readonly title?: ReactNode;
|
readonly title?: ReactNode;
|
||||||
|
readonly className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Admonition(props: Props): JSX.Element;
|
export default function Admonition(props: Props): JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Type/Note' {
|
||||||
|
import type {Props as AdmonitionProps} from '@theme/Admonition';
|
||||||
|
|
||||||
|
export interface Props extends AdmonitionProps {}
|
||||||
|
export default function AdmonitionTypeNote(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Type/Info' {
|
||||||
|
import type {Props as AdmonitionProps} from '@theme/Admonition';
|
||||||
|
|
||||||
|
export interface Props extends AdmonitionProps {}
|
||||||
|
export default function AdmonitionTypeInfo(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Type/Tip' {
|
||||||
|
import type {Props as AdmonitionProps} from '@theme/Admonition';
|
||||||
|
|
||||||
|
export interface Props extends AdmonitionProps {}
|
||||||
|
export default function AdmonitionTypeTip(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Type/Caution' {
|
||||||
|
import type {Props as AdmonitionProps} from '@theme/Admonition';
|
||||||
|
|
||||||
|
export interface Props extends AdmonitionProps {}
|
||||||
|
export default function AdmonitionTypeCaution(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Type/Danger' {
|
||||||
|
import type {Props as AdmonitionProps} from '@theme/Admonition';
|
||||||
|
|
||||||
|
export interface Props extends AdmonitionProps {}
|
||||||
|
export default function AdmonitionTypeDanger(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Types' {
|
||||||
|
import type {ComponentType} from 'react';
|
||||||
|
import type {Props} from '@theme/Admonition';
|
||||||
|
|
||||||
|
const AdmonitionTypes: {
|
||||||
|
[admonitionType: string]: ComponentType<Props>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AdmonitionTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Layout' {
|
||||||
|
import type {ReactNode} from 'react';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
readonly children: ReactNode;
|
||||||
|
readonly type: string;
|
||||||
|
readonly icon?: ReactNode;
|
||||||
|
readonly title?: ReactNode;
|
||||||
|
readonly className?: string;
|
||||||
|
}
|
||||||
|
export default function AdmonitionLayout(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Icon/Note' {
|
||||||
|
import type {ComponentProps} from 'react';
|
||||||
|
|
||||||
|
export interface Props extends ComponentProps<'svg'> {}
|
||||||
|
|
||||||
|
export default function AdmonitionIconNote(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Icon/Tip' {
|
||||||
|
import type {ComponentProps} from 'react';
|
||||||
|
|
||||||
|
export interface Props extends ComponentProps<'svg'> {}
|
||||||
|
|
||||||
|
export default function AdmonitionIconTip(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Icon/Caution' {
|
||||||
|
import type {ComponentProps} from 'react';
|
||||||
|
|
||||||
|
export interface Props extends ComponentProps<'svg'> {}
|
||||||
|
|
||||||
|
export default function AdmonitionIconCaution(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Icon/Danger' {
|
||||||
|
import type {ComponentProps} from 'react';
|
||||||
|
|
||||||
|
export interface Props extends ComponentProps<'svg'> {}
|
||||||
|
|
||||||
|
export default function AdmonitionIconDanger(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Admonition/Icon/Info' {
|
||||||
|
import type {ComponentProps} from 'react';
|
||||||
|
|
||||||
|
export interface Props extends ComponentProps<'svg'> {}
|
||||||
|
|
||||||
|
export default function AdmonitionIconInfo(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
declare module '@theme/AnnouncementBar' {
|
declare module '@theme/AnnouncementBar' {
|
||||||
export default function AnnouncementBar(): JSX.Element | null;
|
export default function AnnouncementBar(): JSX.Element | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import type {Props} from '@theme/Admonition/Icon/Caution';
|
||||||
|
|
||||||
|
export default function AdmonitionIconCaution(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg viewBox="0 0 16 16" {...props}>
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import type {Props} from '@theme/Admonition/Icon/Danger';
|
||||||
|
|
||||||
|
export default function AdmonitionIconDanger(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg viewBox="0 0 12 16" {...props}>
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import type {Props} from '@theme/Admonition/Icon/Info';
|
||||||
|
|
||||||
|
export default function AdmonitionIconInfo(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg viewBox="0 0 14 16" {...props}>
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import type {Props} from '@theme/Admonition/Icon/Note';
|
||||||
|
|
||||||
|
export default function AdmonitionIconNote(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg viewBox="0 0 14 16" {...props}>
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import type {Props} from '@theme/Admonition/Icon/Tip';
|
||||||
|
|
||||||
|
export default function AdmonitionIconTip(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg viewBox="0 0 12 16" {...props}>
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* 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 React, {type ReactNode} from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
|
import type {Props} from '@theme/Admonition/Layout';
|
||||||
|
|
||||||
|
import styles from './styles.module.css';
|
||||||
|
|
||||||
|
function AdmonitionContainer({
|
||||||
|
type,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
}: Pick<Props, 'type' | 'className'> & {children: ReactNode}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
ThemeClassNames.common.admonition,
|
||||||
|
ThemeClassNames.common.admonitionType(type),
|
||||||
|
styles.admonition,
|
||||||
|
className,
|
||||||
|
)}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AdmonitionHeading({icon, title}: Pick<Props, 'icon' | 'title'>) {
|
||||||
|
return (
|
||||||
|
<div className={styles.admonitionHeading}>
|
||||||
|
<span className={styles.admonitionIcon}>{icon}</span>
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AdmonitionContent({children}: Pick<Props, 'children'>) {
|
||||||
|
return <div className={styles.admonitionContent}>{children}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AdmonitionLayout(props: Props): JSX.Element {
|
||||||
|
const {type, icon, title, children, className} = props;
|
||||||
|
return (
|
||||||
|
<AdmonitionContainer type={type} className={className}>
|
||||||
|
<AdmonitionHeading title={title} icon={icon} />
|
||||||
|
<AdmonitionContent>{children}</AdmonitionContent>
|
||||||
|
</AdmonitionContainer>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
|
import type {Props} from '@theme/Admonition/Type/Caution';
|
||||||
|
import AdmonitionLayout from '@theme/Admonition/Layout';
|
||||||
|
import IconCaution from '@theme/Admonition/Icon/Caution';
|
||||||
|
|
||||||
|
const infimaClassName = 'alert alert--warning';
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
icon: <IconCaution />,
|
||||||
|
title: (
|
||||||
|
<Translate
|
||||||
|
id="theme.admonition.caution"
|
||||||
|
description="The default label used for the Caution admonition (:::caution)">
|
||||||
|
caution
|
||||||
|
</Translate>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AdmonitionTypeCaution(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<AdmonitionLayout
|
||||||
|
{...defaultProps}
|
||||||
|
{...props}
|
||||||
|
className={clsx(infimaClassName, props.className)}>
|
||||||
|
{props.children}
|
||||||
|
</AdmonitionLayout>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
|
import type {Props} from '@theme/Admonition/Type/Danger';
|
||||||
|
import AdmonitionLayout from '@theme/Admonition/Layout';
|
||||||
|
import IconDanger from '@theme/Admonition/Icon/Danger';
|
||||||
|
|
||||||
|
const infimaClassName = 'alert alert--danger';
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
icon: <IconDanger />,
|
||||||
|
title: (
|
||||||
|
<Translate
|
||||||
|
id="theme.admonition.danger"
|
||||||
|
description="The default label used for the Danger admonition (:::danger)">
|
||||||
|
danger
|
||||||
|
</Translate>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AdmonitionTypeDanger(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<AdmonitionLayout
|
||||||
|
{...defaultProps}
|
||||||
|
{...props}
|
||||||
|
className={clsx(infimaClassName, props.className)}>
|
||||||
|
{props.children}
|
||||||
|
</AdmonitionLayout>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
|
import type {Props} from '@theme/Admonition/Type/Info';
|
||||||
|
import AdmonitionLayout from '@theme/Admonition/Layout';
|
||||||
|
import IconInfo from '@theme/Admonition/Icon/Info';
|
||||||
|
|
||||||
|
const infimaClassName = 'alert alert--info';
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
icon: <IconInfo />,
|
||||||
|
title: (
|
||||||
|
<Translate
|
||||||
|
id="theme.admonition.info"
|
||||||
|
description="The default label used for the Info admonition (:::info)">
|
||||||
|
info
|
||||||
|
</Translate>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AdmonitionTypeInfo(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<AdmonitionLayout
|
||||||
|
{...defaultProps}
|
||||||
|
{...props}
|
||||||
|
className={clsx(infimaClassName, props.className)}>
|
||||||
|
{props.children}
|
||||||
|
</AdmonitionLayout>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
|
import type {Props} from '@theme/Admonition/Type/Note';
|
||||||
|
import AdmonitionLayout from '@theme/Admonition/Layout';
|
||||||
|
import IconNote from '@theme/Admonition/Icon/Note';
|
||||||
|
|
||||||
|
const infimaClassName = 'alert alert--secondary';
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
icon: <IconNote />,
|
||||||
|
title: (
|
||||||
|
<Translate
|
||||||
|
id="theme.admonition.note"
|
||||||
|
description="The default label used for the Note admonition (:::note)">
|
||||||
|
note
|
||||||
|
</Translate>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AdmonitionTypeNote(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<AdmonitionLayout
|
||||||
|
{...defaultProps}
|
||||||
|
{...props}
|
||||||
|
className={clsx(infimaClassName, props.className)}>
|
||||||
|
{props.children}
|
||||||
|
</AdmonitionLayout>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
|
import type {Props} from '@theme/Admonition/Type/Tip';
|
||||||
|
import AdmonitionLayout from '@theme/Admonition/Layout';
|
||||||
|
import IconTip from '@theme/Admonition/Icon/Tip';
|
||||||
|
|
||||||
|
const infimaClassName = 'alert alert--success';
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
icon: <IconTip />,
|
||||||
|
title: (
|
||||||
|
<Translate
|
||||||
|
id="theme.admonition.tip"
|
||||||
|
description="The default label used for the Tip admonition (:::tip)">
|
||||||
|
tip
|
||||||
|
</Translate>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AdmonitionTypeTip(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<AdmonitionLayout
|
||||||
|
{...defaultProps}
|
||||||
|
{...props}
|
||||||
|
className={clsx(infimaClassName, props.className)}>
|
||||||
|
{props.children}
|
||||||
|
</AdmonitionLayout>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import AdmonitionTypeNote from '@theme/Admonition/Type/Note';
|
||||||
|
import AdmonitionTypeTip from '@theme/Admonition/Type/Tip';
|
||||||
|
import AdmonitionTypeInfo from '@theme/Admonition/Type/Info';
|
||||||
|
import AdmonitionTypeCaution from '@theme/Admonition/Type/Caution';
|
||||||
|
import AdmonitionTypeDanger from '@theme/Admonition/Type/Danger';
|
||||||
|
import type AdmonitionTypes from '@theme/Admonition/Types';
|
||||||
|
|
||||||
|
const admonitionTypes: typeof AdmonitionTypes = {
|
||||||
|
note: AdmonitionTypeNote,
|
||||||
|
tip: AdmonitionTypeTip,
|
||||||
|
info: AdmonitionTypeInfo,
|
||||||
|
caution: AdmonitionTypeCaution,
|
||||||
|
danger: AdmonitionTypeDanger,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Undocumented legacy admonition type aliases
|
||||||
|
// Provide hardcoded/untranslated retrocompatible label
|
||||||
|
// See also https://github.com/facebook/docusaurus/issues/7767
|
||||||
|
const admonitionAliases: typeof AdmonitionTypes = {
|
||||||
|
secondary: (props) => <AdmonitionTypeNote title="secondary" {...props} />,
|
||||||
|
important: (props) => <AdmonitionTypeInfo title="important" {...props} />,
|
||||||
|
success: (props) => <AdmonitionTypeTip title="success" {...props} />,
|
||||||
|
// TODO bad legacy mapping, warning is usually yellow, not red...
|
||||||
|
warning: (props) => <AdmonitionTypeDanger title="warning" {...props} />,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
...admonitionTypes,
|
||||||
|
...admonitionAliases,
|
||||||
|
};
|
|
@ -5,205 +5,24 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {type ReactNode} from 'react';
|
import React, {type ComponentType} from 'react';
|
||||||
import clsx from 'clsx';
|
import {processAdmonitionProps} from '@docusaurus/theme-common';
|
||||||
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
||||||
import Translate from '@docusaurus/Translate';
|
|
||||||
import type {Props} from '@theme/Admonition';
|
import type {Props} from '@theme/Admonition';
|
||||||
|
import AdmonitionTypes from '@theme/Admonition/Types';
|
||||||
|
|
||||||
import styles from './styles.module.css';
|
function getAdmonitionTypeComponent(type: string): ComponentType<Props> {
|
||||||
|
const component = AdmonitionTypes[type];
|
||||||
function NoteIcon() {
|
if (component) {
|
||||||
return (
|
return component;
|
||||||
<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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
label: ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
|
|
||||||
const AdmonitionConfigs: Record<Props['type'], AdmonitionConfig> = {
|
|
||||||
note: {
|
|
||||||
infimaClassName: 'secondary',
|
|
||||||
iconComponent: NoteIcon,
|
|
||||||
label: (
|
|
||||||
<Translate
|
|
||||||
id="theme.admonition.note"
|
|
||||||
description="The default label used for the Note admonition (:::note)">
|
|
||||||
note
|
|
||||||
</Translate>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
tip: {
|
|
||||||
infimaClassName: 'success',
|
|
||||||
iconComponent: TipIcon,
|
|
||||||
label: (
|
|
||||||
<Translate
|
|
||||||
id="theme.admonition.tip"
|
|
||||||
description="The default label used for the Tip admonition (:::tip)">
|
|
||||||
tip
|
|
||||||
</Translate>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
danger: {
|
|
||||||
infimaClassName: 'danger',
|
|
||||||
iconComponent: DangerIcon,
|
|
||||||
label: (
|
|
||||||
<Translate
|
|
||||||
id="theme.admonition.danger"
|
|
||||||
description="The default label used for the Danger admonition (:::danger)">
|
|
||||||
danger
|
|
||||||
</Translate>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
info: {
|
|
||||||
infimaClassName: 'info',
|
|
||||||
iconComponent: InfoIcon,
|
|
||||||
label: (
|
|
||||||
<Translate
|
|
||||||
id="theme.admonition.info"
|
|
||||||
description="The default label used for the Info admonition (:::info)">
|
|
||||||
info
|
|
||||||
</Translate>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
caution: {
|
|
||||||
infimaClassName: 'warning',
|
|
||||||
iconComponent: CautionIcon,
|
|
||||||
label: (
|
|
||||||
<Translate
|
|
||||||
id="theme.admonition.caution"
|
|
||||||
description="The default label used for the Caution admonition (:::caution)">
|
|
||||||
caution
|
|
||||||
</Translate>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Legacy aliases, undocumented but kept for retro-compatibility
|
|
||||||
const aliases = {
|
|
||||||
secondary: 'note',
|
|
||||||
important: 'info',
|
|
||||||
success: 'tip',
|
|
||||||
warning: 'danger',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
function getAdmonitionConfig(unsafeType: string): AdmonitionConfig {
|
|
||||||
const type =
|
|
||||||
(aliases as {[key: string]: Props['type']})[unsafeType] ?? unsafeType;
|
|
||||||
const config = (AdmonitionConfigs as {[key: string]: AdmonitionConfig})[type];
|
|
||||||
if (config) {
|
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
console.warn(
|
console.warn(
|
||||||
`No admonition config found for admonition type "${type}". Using Info as fallback.`,
|
`No admonition component found for admonition type "${type}". Using Info as fallback.`,
|
||||||
);
|
);
|
||||||
return AdmonitionConfigs.info;
|
return AdmonitionTypes.info!;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround because it's difficult in MDX v1 to provide a MDX title as props
|
export default function Admonition(unprocessedProps: Props): JSX.Element {
|
||||||
// See https://github.com/facebook/docusaurus/pull/7152#issuecomment-1145779682
|
const props = processAdmonitionProps(unprocessedProps);
|
||||||
function extractMDXAdmonitionTitle(children: ReactNode): {
|
const AdmonitionTypeComponent = getAdmonitionTypeComponent(props.type);
|
||||||
mdxAdmonitionTitle: ReactNode | undefined;
|
return <AdmonitionTypeComponent {...props} />;
|
||||||
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,
|
|
||||||
children: rest,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Admonition(props: Props): JSX.Element {
|
|
||||||
const {children, type, title, icon: iconProp} = processAdmonitionProps(props);
|
|
||||||
|
|
||||||
const typeConfig = getAdmonitionConfig(type);
|
|
||||||
const titleLabel = title ?? typeConfig.label;
|
|
||||||
const {iconComponent: IconComponent} = typeConfig;
|
|
||||||
const icon = iconProp ?? <IconComponent />;
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
ThemeClassNames.common.admonition,
|
|
||||||
ThemeClassNames.common.admonitionType(props.type),
|
|
||||||
'alert',
|
|
||||||
`alert--${typeConfig.infimaClassName}`,
|
|
||||||
styles.admonition,
|
|
||||||
)}>
|
|
||||||
<div className={styles.admonitionHeading}>
|
|
||||||
<span className={styles.admonitionIcon}>{icon}</span>
|
|
||||||
{titleLabel}
|
|
||||||
</div>
|
|
||||||
<div className={styles.admonitionContent}>{children}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,3 +78,5 @@ export {duplicates, uniq} from './utils/jsUtils';
|
||||||
export {usePrismTheme} from './hooks/usePrismTheme';
|
export {usePrismTheme} from './hooks/usePrismTheme';
|
||||||
|
|
||||||
export {useDocsPreferredVersion} from './contexts/docsPreferredVersion';
|
export {useDocsPreferredVersion} from './contexts/docsPreferredVersion';
|
||||||
|
|
||||||
|
export {processAdmonitionProps} from './utils/admonitionUtils';
|
||||||
|
|
|
@ -40,8 +40,7 @@ export const ThemeClassNames = {
|
||||||
backToTopButton: 'theme-back-to-top-button',
|
backToTopButton: 'theme-back-to-top-button',
|
||||||
codeBlock: 'theme-code-block',
|
codeBlock: 'theme-code-block',
|
||||||
admonition: 'theme-admonition',
|
admonition: 'theme-admonition',
|
||||||
admonitionType: (type: 'note' | 'tip' | 'danger' | 'info' | 'caution') =>
|
admonitionType: (type: string) => `theme-admonition-${type}`,
|
||||||
`theme-admonition-${type}`,
|
|
||||||
},
|
},
|
||||||
layout: {
|
layout: {
|
||||||
// TODO add other stable classNames here
|
// TODO add other stable classNames here
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* 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 React, {type ReactNode} from 'react';
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function processAdmonitionProps<
|
||||||
|
Props extends {readonly children: ReactNode; readonly title?: ReactNode},
|
||||||
|
>(props: Props): Props {
|
||||||
|
const {mdxAdmonitionTitle, rest} = extractMDXAdmonitionTitle(props.children);
|
||||||
|
const title = props.title ?? mdxAdmonitionTitle;
|
||||||
|
return {
|
||||||
|
...props,
|
||||||
|
// Do not return "title: undefined" prop
|
||||||
|
// this might create unwanted props overrides when merging props
|
||||||
|
// For example: {...default,...props}
|
||||||
|
...(title && {title}),
|
||||||
|
children: rest,
|
||||||
|
};
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ You now need to swizzle the admonitions component to provide UI customizations s
|
||||||
Please refer to https://github.com/facebook/docusaurus/pull/7152 for detailed upgrade instructions."
|
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={"keywords":["custom-keyword"],"extendDefaults":42} 1`] = `""extendDefaults" must be a boolean"`;
|
||||||
|
|
||||||
exports[`validation schemas admonitionsSchema: for value={"tag":""} 1`] = `""tag" is not allowed to be empty"`;
|
exports[`validation schemas admonitionsSchema: for value={"tag":""} 1`] = `""tag" is not allowed to be empty"`;
|
||||||
|
|
||||||
|
|
|
@ -96,13 +96,20 @@ describe('validation schemas', () => {
|
||||||
testOK({});
|
testOK({});
|
||||||
testOK({tag: '+++'});
|
testOK({tag: '+++'});
|
||||||
testOK({keywords: ['info', 'tip']});
|
testOK({keywords: ['info', 'tip']});
|
||||||
|
testOK({keywords: ['info', 'tip'], extendDefaults: true});
|
||||||
|
testOK({keywords: ['info', 'tip'], extendDefaults: false});
|
||||||
|
testOK({keywords: []});
|
||||||
|
testOK({keywords: [], extendDefaults: true}); // noop
|
||||||
|
testOK({keywords: [], extendDefaults: false}); // disable admonitions
|
||||||
testOK({tag: '+++', keywords: ['info', 'tip']});
|
testOK({tag: '+++', keywords: ['info', 'tip']});
|
||||||
|
testOK({tag: '+++', keywords: ['custom-keyword'], extendDefaults: true});
|
||||||
|
testOK({tag: '+++', keywords: ['custom-keyword'], extendDefaults: false});
|
||||||
|
|
||||||
testFail(3);
|
testFail(3);
|
||||||
testFail([]);
|
testFail([]);
|
||||||
testFail({unknownAttribute: 'val'});
|
testFail({unknownAttribute: 'val'});
|
||||||
testFail({tag: ''});
|
testFail({tag: ''});
|
||||||
testFail({keywords: []});
|
testFail({keywords: ['custom-keyword'], extendDefaults: 42});
|
||||||
|
|
||||||
// Legacy types
|
// Legacy types
|
||||||
testFail({
|
testFail({
|
||||||
|
|
|
@ -44,8 +44,12 @@ export const AdmonitionsSchema = JoiFrontMatter.alternatives()
|
||||||
JoiFrontMatter.object({
|
JoiFrontMatter.object({
|
||||||
tag: JoiFrontMatter.string(),
|
tag: JoiFrontMatter.string(),
|
||||||
keywords: JoiFrontMatter.array().items(
|
keywords: JoiFrontMatter.array().items(
|
||||||
JoiFrontMatter.string().required(),
|
JoiFrontMatter.string(),
|
||||||
|
// Apparently this is how we tell job to accept empty arrays...
|
||||||
|
// .required(),
|
||||||
),
|
),
|
||||||
|
extendDefaults: JoiFrontMatter.boolean(),
|
||||||
|
|
||||||
// TODO Remove before 2023
|
// TODO Remove before 2023
|
||||||
customTypes: LegacyAdmonitionConfigSchema,
|
customTypes: LegacyAdmonitionConfigSchema,
|
||||||
icons: LegacyAdmonitionConfigSchema,
|
icons: LegacyAdmonitionConfigSchema,
|
||||||
|
|
|
@ -50,7 +50,7 @@ function sortComponentNames(componentNames: string[]): string[] {
|
||||||
*
|
*
|
||||||
* @param componentNames the original list of component names
|
* @param componentNames the original list of component names
|
||||||
*/
|
*/
|
||||||
function getMissingIntermediateComponentFolderNames(
|
export function getMissingIntermediateComponentFolderNames(
|
||||||
componentNames: string[],
|
componentNames: string[],
|
||||||
): string[] {
|
): string[] {
|
||||||
function getAllIntermediatePaths(componentName: string): string[] {
|
function getAllIntermediatePaths(componentName: string): string[] {
|
||||||
|
|
|
@ -239,3 +239,9 @@ Can be arbitrarily nested:
|
||||||
Admonition body
|
Admonition body
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
:::important
|
||||||
|
|
||||||
|
Admonition alias `:::important` should have Important title
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
|
@ -13,7 +13,10 @@ import logger from '@docusaurus/logger';
|
||||||
import classicTheme from '@docusaurus/theme-classic';
|
import classicTheme from '@docusaurus/theme-classic';
|
||||||
|
|
||||||
// Unsafe imports
|
// Unsafe imports
|
||||||
import {readComponentNames} from '@docusaurus/core/lib/commands/swizzle/components.js';
|
import {
|
||||||
|
readComponentNames,
|
||||||
|
getMissingIntermediateComponentFolderNames,
|
||||||
|
} from '@docusaurus/core/lib/commands/swizzle/components.js';
|
||||||
import {normalizeSwizzleConfig} from '@docusaurus/core/lib/commands/swizzle/config.js';
|
import {normalizeSwizzleConfig} from '@docusaurus/core/lib/commands/swizzle/config.js';
|
||||||
import {wrap, eject} from '@docusaurus/core/lib/commands/swizzle/actions.js';
|
import {wrap, eject} from '@docusaurus/core/lib/commands/swizzle/actions.js';
|
||||||
|
|
||||||
|
@ -50,7 +53,33 @@ console.log('\n');
|
||||||
|
|
||||||
await fs.remove(toPath);
|
await fs.remove(toPath);
|
||||||
|
|
||||||
let componentNames = await readComponentNames(themePath);
|
function filterComponentNames(componentNames) {
|
||||||
|
// TODO temp workaround: non-comps should be forbidden to wrap
|
||||||
|
if (action === 'wrap') {
|
||||||
|
const WrapBlocklist = [
|
||||||
|
'Layout', // Due to theme-fallback?
|
||||||
|
];
|
||||||
|
|
||||||
|
return componentNames.filter((componentName) => {
|
||||||
|
const blocked = WrapBlocklist.includes(componentName);
|
||||||
|
if (blocked) {
|
||||||
|
logger.warn(`${componentName} is blocked and will not be wrapped`);
|
||||||
|
}
|
||||||
|
return !blocked;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return componentNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllComponentNames() {
|
||||||
|
const names = await readComponentNames(themePath);
|
||||||
|
const allNames = names.concat(
|
||||||
|
await getMissingIntermediateComponentFolderNames(names),
|
||||||
|
);
|
||||||
|
return filterComponentNames(allNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
const componentNames = await getAllComponentNames();
|
||||||
|
|
||||||
const componentsNotFound = Object.keys(swizzleConfig.components).filter(
|
const componentsNotFound = Object.keys(swizzleConfig.components).filter(
|
||||||
(componentName) => !componentNames.includes(componentName),
|
(componentName) => !componentNames.includes(componentName),
|
||||||
|
@ -67,21 +96,6 @@ Please double-check or clean up these components from the config:
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO temp workaround: non-comps should be forbidden to wrap
|
|
||||||
if (action === 'wrap') {
|
|
||||||
const WrapBlocklist = [
|
|
||||||
'Layout', // Due to theme-fallback?
|
|
||||||
];
|
|
||||||
|
|
||||||
componentNames = componentNames.filter((componentName) => {
|
|
||||||
const blocked = WrapBlocklist.includes(componentName);
|
|
||||||
if (blocked) {
|
|
||||||
logger.warn(`${componentName} is blocked and will not be wrapped`);
|
|
||||||
}
|
|
||||||
return !blocked;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} componentName
|
* @param {string} componentName
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -216,13 +216,13 @@ You can customize how each individual admonition type is rendered through [swizz
|
||||||
```jsx title="src/theme/Admonition.js"
|
```jsx title="src/theme/Admonition.js"
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Admonition from '@theme-original/Admonition';
|
import Admonition from '@theme-original/Admonition';
|
||||||
import MyIcon from '@site/static/img/info.svg';
|
import MyCustomNoteIcon from '@site/static/img/info.svg';
|
||||||
|
|
||||||
export default function AdmonitionWrapper(props) {
|
export default function AdmonitionWrapper(props) {
|
||||||
if (props.type !== 'info') {
|
if (props.type !== 'info') {
|
||||||
return <Admonition {...props} />;
|
return <Admonition title="My Custom Admonition Title" {...props} />;
|
||||||
}
|
}
|
||||||
return <Admonition icon={<MyIcon />} {...props} />;
|
return <Admonition icon={<MyCustomNoteIcon />} {...props} />;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -240,6 +240,7 @@ module.exports = {
|
||||||
admonitions: {
|
admonitions: {
|
||||||
tag: ':::',
|
tag: ':::',
|
||||||
keywords: ['note', 'tip', 'info', 'caution', 'danger'],
|
keywords: ['note', 'tip', 'info', 'caution', 'danger'],
|
||||||
|
extendDefaults: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -248,9 +249,82 @@ module.exports = {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
The plugin accepts two options:
|
The plugin accepts the following options:
|
||||||
|
|
||||||
- `tag`: The tag that encloses the admonition. Defaults to `:::`.
|
- `tag`: The tag that encloses the admonition. Defaults to `:::`.
|
||||||
- `keywords`: An array of keywords that can be used as the type for the admonition. Note that if you override this, the default values will not be applied.
|
- `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. If you register more types than the default, you are also responsible for providing their implementation—including the container's style, icon, default title text, etc. You would usually need to [eject](../../swizzling.md#ejecting) the `@theme/Admonition` component, so you could re-use the same infrastructure as the other types.
|
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>
|
||||||
|
|
|
@ -303,6 +303,9 @@ const config = {
|
||||||
const nextVersionDocsDirPath = 'docs';
|
const nextVersionDocsDirPath = 'docs';
|
||||||
return `https://github.com/facebook/docusaurus/edit/main/website/${nextVersionDocsDirPath}/${docPath}`;
|
return `https://github.com/facebook/docusaurus/edit/main/website/${nextVersionDocsDirPath}/${docPath}`;
|
||||||
},
|
},
|
||||||
|
admonitions: {
|
||||||
|
keywords: ['my-custom-admonition'],
|
||||||
|
},
|
||||||
showLastUpdateAuthor: true,
|
showLastUpdateAuthor: true,
|
||||||
showLastUpdateTime: true,
|
showLastUpdateTime: true,
|
||||||
remarkPlugins: [math, [npm2yarn, {sync: true}]],
|
remarkPlugins: [math, [npm2yarn, {sync: true}]],
|
||||||
|
|
29
website/src/theme/Admonition/Types.tsx
Normal file
29
website/src/theme/Admonition/Types.tsx
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
* 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 React from 'react';
|
||||||
|
import type {Props} from '@theme/Admonition';
|
||||||
|
import DefaultAdmonitionTypes from '@theme-original/Admonition/Types';
|
||||||
|
|
||||||
|
function MyCustomAdmonition(props: Props): JSX.Element {
|
||||||
|
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
|
||||||
|
'my-custom-admonition': MyCustomAdmonition,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AdmonitionTypes;
|
Loading…
Add table
Add a link
Reference in a new issue