From bac292d84b0371b92549892dc2b46f2bf737b46c Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Thu, 26 May 2022 21:50:50 +0800 Subject: [PATCH] docs: document MDXComponents scope (#7503) * docs: document MDXComponents scope * address reviews * add info --- .../markdown-features-react.mdx | 70 ++++++++++++++++++- website/src/components/Highlight.tsx | 28 ++++++++ website/src/theme/MDXComponents.tsx | 14 ++++ 3 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 website/src/components/Highlight.tsx create mode 100644 website/src/theme/MDXComponents.tsx diff --git a/website/docs/guides/markdown-features/markdown-features-react.mdx b/website/docs/guides/markdown-features/markdown-features-react.mdx index 6422961e3c34..ca1588df16b1 100644 --- a/website/docs/guides/markdown-features/markdown-features-react.mdx +++ b/website/docs/guides/markdown-features/markdown-features-react.mdx @@ -24,7 +24,11 @@ While Docusaurus parses both `.md` and `.mdx` files using MDX, some of the synta ::: -To define any custom component within an MDX file, you have to export it. +Check out the [MDX docs](https://mdxjs.com/) to see what other fancy stuff you can do with MDX. + +### Exporting components {#exporting-components} + +To define any custom component within an MDX file, you have to export it: only paragraphs that start with `export` will be parsed as components instead of prose. ```jsx export const Highlight = ({children, color}) => ( @@ -133,7 +137,69 @@ import Highlight from '@site/src/components/Highlight'; Docusaurus green ``` -Check out the [MDX docs](https://mdxjs.com/) to see what other fancy stuff you can do with MDX. +:::tip + +If you use the same component across a lot of files, you don't need to import it everywhere—consider adding it to the global scope. [See below](#mdx-component-scope) + +::: + +### MDX component scope {#mdx-component-scope} + +Apart from [importing a component](#importing-components) and [exporting a component](#exporting-components), a third way to use a component in MDX is to **register it to the global scope**, which will make it automatically available in every MDX file, without any import statements. + +For example, given this MDX file: + +```md +- a +- list! + +And some custom markup... +``` + +It will be compiled to a React component containing `ul`, `li`, `p`, and `highlight` tags. Now, you can optionally provide your own implementation for any of these tags in the form of React components. (`highlight` isn't even an intrinsic element: it needs an implementation!) + +In Docusaurus, this MDX component scope is provided by the `@theme/MDXComponents` component. It's not a React component, _per se_, unlike most other exports under the `@theme/` alias: it is a record from tag names like `ul` and `img` to their custom implementations. + +If you [swizzle](../../swizzling.md) this component, you will find all tags that have been re-implemented, and you can further customize our implementation by swizzling the respective sub-component, like `@theme/MDXComponents/Head` (which is used to implement the [``](./markdown-features-head-metadata.mdx) feature). + +If you want to register extra tag names (like the `` tag above), you should consider [wrapping `@theme/MDXComponents`](../../swizzling.md#wrapping), so you don't have to maintain all the existing mappings. Since the swizzle CLI doesn't allow wrapping non-component files yet, you should manually create the wrapper: + +```js title="src/theme/MDXComponents.js" +import React from 'react'; +// Import the original mapper +import MDXComponents from '@theme-original/MDXComponents'; +// highlight-next-line +import Highlight from '@site/src/components/Highlight'; + +export default { + // Re-use the default mapping + ...MDXComponents, + // Map the "highlight" tag to our component! + // `Highlight` will receive all props that were passed to `highlight` in MDX + // highlight-next-line + highlight: Highlight, +}; +``` + +And now, you can freely use `` in every page, without writing the import statement: + +```md +I can conveniently use Docusaurus green everywhere! +``` + +```mdx-code-block + + +I can conveniently use Docusaurus green everywhere! + + +``` + +:::info + +We use lower-case tag names like `highlight` to "pretend" that they are intrinsic elements, but you can use capitalized ones like `Highlight` as well. + +::: ### Markdown and JSX interoperability {#markdown-and-jsx-interoperability} diff --git a/website/src/components/Highlight.tsx b/website/src/components/Highlight.tsx new file mode 100644 index 000000000000..ad7e214a9f8d --- /dev/null +++ b/website/src/components/Highlight.tsx @@ -0,0 +1,28 @@ +/** + * 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'; + +export default function Highlight({ + children, + color, +}: { + children: ReactNode; + color: string; +}): JSX.Element { + return ( + + {children} + + ); +} diff --git a/website/src/theme/MDXComponents.tsx b/website/src/theme/MDXComponents.tsx new file mode 100644 index 000000000000..1005f7b2c77e --- /dev/null +++ b/website/src/theme/MDXComponents.tsx @@ -0,0 +1,14 @@ +/** + * 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 MDXComponents from '@theme-original/MDXComponents'; +import Highlight from '@site/src/components/Highlight'; + +export default { + ...MDXComponents, + highlight: Highlight, +};