chore: prepare v2.0.0-beta.19 release (#7325)

* chore: prepare v2.0.0-beta.19 release

* v2.0.0-beta.19
This commit is contained in:
Alexey Pyltsyn 2022-05-04 18:38:45 +03:00 committed by GitHub
parent 7944fdd9a2
commit 6fa51890f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
134 changed files with 1971 additions and 923 deletions

View file

@ -1,39 +0,0 @@
---
id: markdown-features
title: Docs Markdown Features
description: Docusaurus Markdown features that are specific to the docs plugin
slug: /docs-markdown-features
---
Docs can use any [Markdown feature](../markdown-features/markdown-features-intro.mdx) and have a few additional docs-specific Markdown features.
## Markdown front matter {#markdown-front-matter}
Markdown docs have their own [Markdown front matter API](../../api/plugins/plugin-content-docs.md#markdown-front-matter).
## Referencing other documents {#referencing-other-documents}
If you want to reference another document file, you could use the relative path of the document you want to link to.
Docusaurus will convert the file path to be the final document url path (and remove the `.md` extension).
For example, if you are in `folder/doc1.md` and you want to reference `folder/doc2.md`, `folder/subfolder/doc3.md` and `otherFolder/doc4.md`:
```md
I am referencing a [document](doc2.md).
Reference to another [document in a subfolder](subfolder/doc3.md).
[Relative document](../otherFolder/doc4.md) referencing works as well.
```
:::tip
Using relative _file_ paths (with `.md` extensions) instead of relative _URL_ links provides the following benefits:
- links will keep working on the GitHub interface
- you can customize the document slugs without having to update all the links
- a versioned doc will link to another doc of the exact same version
- relative links are very likely to break if you update the [`trailingSlash` config](../../api/docusaurus.config.js.md#trailing-slash)
:::

View file

@ -1,67 +0,0 @@
---
id: head-metadata
title: Head Metadata
description: Declaring page-specific head metadata through MDX
slug: /markdown-features/head-metadata
---
# Head Metadata
Docusaurus automatically sets useful page metadata in `<html>`, `<head>` and `<body>` for you.
It is possible to add extra metadata (or override existing ones) by using the `<head>` tag in Markdown files:
```md title="markdown-features-head-metadata.mdx"
---
id: head-metadata
title: Head Metadata
---
<!-- highlight-start -->
<head>
<html className="some-extra-html-class" />
<body className="other-extra-body-class" />
<title>Head Metadata customized title!</title>
<meta charSet="utf-8" />
<meta name="twitter:card" content="summary" />
<link rel="canonical" href="https://docusaurus.io/docs/markdown-features/head-metadata" />
</head>
<!-- highlight-end -->
# Head Metadata
My text
```
```mdx-code-block
<head>
<html className="some-extra-html-class" />
<body className="other-extra-body-class" />
<title>Head Metadata customized title!</title>
<meta charSet="utf-8" />
<meta name="twitter:card" content="summary" />
<link rel="canonical" href="https://docusaurus.io/docs/markdown-features/head-metadata" />
</head>
```
:::tip
This `<head>` declaration has been added to the current Markdown doc, as a demo.
Open your browser DevTools and check how this page's metadata has been affected.
:::
:::tip
**You don't always need this for typical SEO needs.** Content plugins (e.g. docs and blog) provide front matter options like `description`, `keywords`, and `image`, which will be automatically applied to both `description` and `og:description`, while you would have to manually declare two metadata tags when using the `<head>` tag.
:::
:::note
This feature is built on top of the Docusaurus [`<Head>`](./../../docusaurus-core.md#head) component.
Refer to [react-helmet](https://github.com/nfl/react-helmet) for exhaustive documentation.
:::

View file

@ -1,57 +0,0 @@
---
id: headings
title: Headings
description: Using Markdown headings
slug: /markdown-features/headings
---
## Markdown headings {#markdown-headings}
You can use regular Markdown headings.
```
## Level 2 title
### Level 3 title
#### Level 4 title
```
Markdown headings appear as a table of contents entry.
## Heading ids {#heading-ids}
Each heading has an id that can be automatically generated or explicitly specified.
Heading ids allow you to link to a specific document heading in Markdown or JSX:
```md
[link](#heading-id)
```
```jsx
<Link to="#heading-id">link</Link>
```
### Generated ids {#generated-ids}
By default, Docusaurus will generate heading ids for you, based on the heading text. For example, `### Hello World` will have id `hello-world`.
Generated ids have **some limits**:
- The id might not look good
- You might want to **change or translate** the text without updating the existing id
### Explicit ids {#explicit-ids}
A special Markdown syntax lets you set an **explicit heading id**:
```md
### Hello World {#my-explicit-id}
```
:::tip
Use the **[write-heading-ids](../../cli.md#docusaurus-write-heading-ids-sitedir)** CLI command to add explicit ids to all your Markdown documents.
:::

View file

@ -1,173 +0,0 @@
---
id: inline-toc
title: Inline TOC
description: Using inline table-of-contents inside Docusaurus Markdown
slug: /markdown-features/inline-toc
---
import BrowserWindow from '@site/src/components/BrowserWindow';
Each Markdown document displays a tab of content on the top-right corner.
But it is also possible to display an inline table of contents directly inside a markdown document, thanks to MDX.
## Full table of contents {#full-table-of-contents}
The `toc` variable is available in any MDX document and contains all the headings of an MDX document.
By default, only `h2` and `h3` headings are displayed in the TOC. You can change which heading levels are visible by setting `minHeadingLevel` or `maxHeadingLevel`.
```jsx
import TOCInline from '@theme/TOCInline';
<TOCInline toc={toc} />;
```
```mdx-code-block
import TOCInline from '@theme/TOCInline';
<BrowserWindow>
<TOCInline toc={toc} />
</BrowserWindow>
```
## Custom table of contents {#custom-table-of-contents}
The `toc` prop is just a list of heading items:
```ts
type TOCItem = {
value: string;
id: string;
level: number;
};
```
Note that the `toc` global is a flat array, so you can easily cut out unwanted nodes or insert extra nodes, and create a new TOC tree.
```jsx
import TOCInline from '@theme/TOCInline';
<TOCInline
// Only show h2 and h4 headings
toc={toc.filter((node) => node.level === 2 || node.level === 4)}
/>;
```
```mdx-code-block
<BrowserWindow>
<TOCInline toc={toc.filter((node) => node.level === 2 || node.level === 4)} />
</BrowserWindow>
```
---
:::caution
Below is just some dummy content to have more table of contents items available on the current page.
:::
## Example Section 1 {#example-section-1}
Lorem ipsum
### Example Subsection 1 a {#example-subsection-1-a}
Lorem ipsum
#### Example subsubsection 1 a I
#### Example subsubsection 1 a II
#### Example subsubsection 1 a III
### Example Subsection 1 b {#example-subsection-1-b}
Lorem ipsum
#### Example subsubsection 1 b I
#### Example subsubsection 1 b II
#### Example subsubsection 1 b III
### Example Subsection 1 c {#example-subsection-1-c}
Lorem ipsum
#### Example subsubsection 1 c I
#### Example subsubsection 1 c II
#### Example subsubsection 1 c III
## Example Section 2 {#example-section-2}
Lorem ipsum
### Example Subsection 2 a {#example-subsection-2-a}
Lorem ipsum
#### Example subsubsection 2 a I
#### Example subsubsection 2 a II
#### Example subsubsection 2 a III
### Example Subsection 2 b {#example-subsection-2-b}
Lorem ipsum
#### Example subsubsection 2 b I
#### Example subsubsection 2 b II
#### Example subsubsection 2 b III
### Example Subsection 2 c {#example-subsection-2-c}
Lorem ipsum
#### Example subsubsection 2 c I
#### Example subsubsection 2 c II
#### Example subsubsection 2 c III
## Example Section 3 {#example-section-3}
Lorem ipsum
### Example Subsection 3 a {#example-subsection-3-a}
Lorem ipsum
#### Example subsubsection 3 a I
#### Example subsubsection 3 a II
#### Example subsubsection 3 a III
### Example Subsection 3 b {#example-subsection-3-b}
Lorem ipsum
#### Example subsubsection 3 b I
#### Example subsubsection 3 b II
#### Example subsubsection 3 b III
### Example Subsection 3 c {#example-subsection-3-c}
Lorem ipsum
#### Example subsubsection 3 c I
#### Example subsubsection 3 c II
#### Example subsubsection 3 c III

View file

@ -1,3 +1,7 @@
---
description: How the Docusaurus client is structured
---
# Client architecture
## Theme aliases {#theme-aliases}
@ -82,7 +86,7 @@ Client modules are part of your site's bundle, just like theme components. Howev
These modules are imported globally before React even renders the initial UI.
```js title="App.tsx"
```js title="@docusaurus/core/App.tsx"
// How it works under the hood
import '@generated/client-modules';
```
@ -113,5 +117,70 @@ CSS stylesheets imported as client modules are [global](../styling-layout.md#glo
}
```
<!-- TODO client module lifecycles -->
<!-- https://github.com/facebook/docusaurus/issues/3399 -->
### Client module lifecycles {#client-module-lifecycles}
Besides introducing side-effects, client modules can optionally export two lifecycle functions: `onRouteUpdate` and `onRouteDidUpdate`.
Because Docusaurus builds a single-page application, `script` tags will only be executed the first time the page loads, but will not re-execute on page transitions. These lifecycles are useful if you have some imperative JS logic that should execute every time a new page has loaded, e.g., to manipulate DOM elements, to send analytics data, etc.
For every route transition, there will be several important timings:
1. The user clicks a link, which causes the router to change its current location.
2. Docusaurus preloads the next route's assets, while keeping displaying the current page's content.
3. The next route's assets have loaded.
4. The new location's route component gets rendered to DOM.
`onRouteUpdate` will be called at event (2), and `onRouteDidUpdate` will be called at (4). They both receive the current location and the previous location (which can be `null`, if this is the first screen).
`onRouteUpdate` can optionally return a "cleanup" callback, which will be called at (3). For example, if you want to display a progress bar, you can start a timeout in `onRouteUpdate`, and clear the timeout in the callback. (The classic theme already provides an `nprogress` integration this way.)
Note that the new page's DOM is only available during event (4). If you need to manipulate the new page's DOM, you'll likely want to use `onRouteDidUpdate`, which will be fired as soon as the DOM on the new page has mounted.
```js title="myClientModule.js"
import type {Location} from 'history';
export function onRouteDidUpdate({location, previousLocation}) {
// Don't execute if we are still on the same page; the lifecycle may be fired
// because the hash changes (e.g. when navigating between headings)
if (location.pathname !== previousLocation?.pathname) {
const title = document.getElementsByTagName('h1')[0];
if (title) {
title.innerText += '❤️';
}
}
}
export function onRouteUpdate({location, previousLocation}) {
if (location.pathname !== previousLocation?.pathname) {
const progressBarTimeout = window.setTimeout(() => {
nprogress.start();
}, delay);
return () => window.clearTimeout(progressBarTimeout);
}
return undefined;
}
```
Or, if you are using TypeScript and you want to leverage contextual typing:
```ts title="myClientModule.ts"
import type {ClientModule} from '@docusaurus/types';
const module: ClientModule = {
onRouteUpdate({location, previousLocation}) {
// ...
},
onRouteDidUpdate({location, previousLocation}) {
// ...
},
};
export default module;
```
Both lifecycles will fire on first render, but they will not fire on server-side, so you can safely access browser globals in them.
:::tip Prefer using React
Client module lifecycles are purely imperative, and you can't use React hooks or access React contexts within them. If your operations are state-driven or involve complicated DOM manipulations, you should consider [swizzling components](../swizzling.md) instead.
:::

View file

@ -51,7 +51,7 @@ module.exports = {
Then in the folder `my-plugin`, you can create an `index.js` such as this:
```js title="my-plugin.js"
```js title="my-plugin/index.js"
module.exports = async function myPlugin(context, options) {
// ...
return {

View file

@ -257,14 +257,14 @@ If you put some HTML pages under the `static` folder, they will be copied to the
<BrowserWindow>
- <Link data-noBrokenLinkCheck="true" to="/pure-html">/pure-html</Link>
- [/pure-html](/pure-html)
- [pathname:///pure-html](pathname:///pure-html)
</BrowserWindow>
:::tip
The first link will trigger a "broken links detected" check during the production build.
The first link will **not** trigger a "broken links detected" check during the production build, because the respective file actually exists. Nevertheless, when you click on the link, a "page not found" will be displayed until you refresh.
:::

View file

@ -100,6 +100,8 @@ These HTML files are the first to arrive at the user's browser screen when a URL
In CSR-only apps, all DOM elements are generated on client side with React, and the HTML file only ever contains one root element for React to mount DOM to; in SSR, React is already facing a fully built HTML page, and it only needs to correlate the DOM elements with the virtual DOM in its model. This step is called "hydration". After React has hydrated the static markup, the app starts to work as any normal React app.
Note that Docusaurus is ultimately a single-page application, so static site generation is only an optimization (_progressive enhancement_, as it's called), but our functionality does not fully depend on those HTML files. This is contrary to site generators like [Jekyll](https://jekyllrb.com/) and [Docusaurus v1](https://v1.docusaurus.io/), where all files are statically transformed to markup, and interactiveness is added through external JavaScript linked with `<script>` tags. If you inspect the build output, you will still see JS assets under `build/assets/js`, which are, really, the core of Docusaurus.
## Escape hatches {#escape-hatches}
If you want to render any dynamic content on your screen that relies on the browser API to be functional at all, for example:

View file

@ -52,7 +52,7 @@ module.exports = Promise.resolve({
- Type: `string`
Title for your website.
Title for your website. Will be used in metadata and as browser tab title.
```js title="docusaurus.config.js"
module.exports = {
@ -72,11 +72,11 @@ module.exports = {
};
```
### `baseUrl` {#baseurl}
### `baseUrl` {#baseUrl}
- Type: `string`
Base URL for your site. This can also be considered the path after the host. For example, `/metro/` is the base URL of https://facebook.github.io/metro/. For URLs that have no path, the baseUrl should be set to `/`. This field is related to the [url](#url) field.
Base URL for your site. Can be considered as the path after the host. For example, `/metro/` is the base URL of https://facebook.github.io/metro/. For URLs that have no path, the baseUrl should be set to `/`. This field is related to the [url](#url) field. Always has both leading and trailing slash.
```js title="docusaurus.config.js"
module.exports = {
@ -90,7 +90,7 @@ module.exports = {
- Type: `string | undefined`
Path to your site favicon. For example, if your favicon is in `static/img/favicon.ico`:
Path to your site favicon; must be a URL that can be used in link's href. For example, if your favicon is in `static/img/favicon.ico`:
```js title="docusaurus.config.js"
module.exports = {
@ -98,7 +98,7 @@ module.exports = {
};
```
### `trailingSlash` {#trailing-slash}
### `trailingSlash` {#trailingSlash}
- Type: `boolean | undefined`
@ -124,6 +124,8 @@ The i18n configuration object to [localize your site](../i18n/i18n-introduction.
Example:
<!-- cSpell:ignore فارسی -->
```js title="docusaurus.config.js"
module.exports = {
i18n: {
@ -134,26 +136,32 @@ module.exports = {
label: 'English',
direction: 'ltr',
htmlLang: 'en-US',
calendar: 'gregory',
},
fr: {
label: 'Français',
direction: 'ltr',
htmlLang: 'fr-FR',
fa: {
label: 'فارسی',
direction: 'rtl',
htmlLang: 'fa-IR',
calendar: 'persian',
},
},
},
};
```
- `label`: the label to use for this locale
- `direction`: `ltr` (default) or `rtl` (for [right-to-left languages](https://developer.mozilla.org/en-US/docs/Glossary/rtl) like Arabic, Hebrew, etc.)
- `htmlLang`: BCP 47 language tag to use in `<html lang="...">` and in `<link ... hreflang="...">`
- `defaultLocale`: The locale that (1) does not have its name in the base URL (2) gets started with `docusaurus start` without `--locale` option (3) will be used for the `<link hrefLang="x-default">` tag
- `locales`: List of locales deployed on your site. Must contain `defaultLocale`.
- `localeConfigs`: Individual options for each locale.
- `label`: The label displayed for this locale in the locales dropdown.
- `direction`: `ltr` (default) or `rtl` (for [right-to-left languages](https://developer.mozilla.org/en-US/docs/Glossary/rtl) like Arabic, Hebrew, etc.). Used to select the locale's CSS and html meta attribute.
- `htmlLang`: BCP 47 language tag to use in `<html lang="...">` and in `<link ... hreflang="...">`
- `calendar`: the [calendar](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar) used to calculate the date era. Note that it doesn't control the actual string displayed: `MM/DD/YYYY` and `DD/MM/YYYY` are both `gregory`. To choose the format (`DD/MM/YYYY` or `MM/DD/YYYY`), set your locale name to `en-GB` or `en-US` (`en` means `en-US`).
### `noIndex` {#noindex}
### `noIndex` {#noIndex}
- Type: `boolean`
This option adds `<meta name="robots" content="noindex, nofollow">` in pages, to tell search engines to avoid indexing your site (more information [here](https://moz.com/learn/seo/robots-meta-directives)).
This option adds `<meta name="robots" content="noindex, nofollow">` to every page to tell search engines to avoid indexing your site (more information [here](https://moz.com/learn/seo/robots-meta-directives)).
Example:
@ -163,11 +171,11 @@ module.exports = {
};
```
### `onBrokenLinks` {#onbrokenlinks}
### `onBrokenLinks` {#onBrokenLinks}
- Type: `'ignore' | 'log' | 'warn' | 'error' | 'throw'`
The behavior of Docusaurus, when it detects any broken link.
The behavior of Docusaurus when it detects any broken link.
By default, it throws an error, to ensure you never ship any broken link, but you can lower this security if needed.
@ -177,15 +185,15 @@ The broken links detection is only available for a production build (`docusaurus
:::
### `onBrokenMarkdownLinks` {#onbrokenmarkdownlinks}
### `onBrokenMarkdownLinks` {#onBrokenMarkdownLinks}
- Type: `'ignore' | 'log' | 'warn' | 'error' | 'throw'`
The behavior of Docusaurus, when it detects any broken markdown link.
The behavior of Docusaurus when it detects any broken markdown link.
By default, it prints a warning, to let you know about your broken markdown link, but you can change this security if needed.
### `onDuplicateRoutes` {#onduplicateroutes}
### `onDuplicateRoutes` {#onDuplicateRoutes}
- Type: `'ignore' | 'log' | 'warn' | 'error' | 'throw'`
@ -206,11 +214,11 @@ module.exports = {
};
```
### `organizationName` {#organizationname}
### `organizationName` {#organizationName}
- Type: `string`
The GitHub user or organization that owns the repository. Used by the deployment command.
The GitHub user or organization that owns the repository. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
module.exports = {
@ -219,11 +227,11 @@ module.exports = {
};
```
### `projectName` {#projectname}
### `projectName` {#projectName}
- Type: `string`
The name of the GitHub repository. Used by the deployment command.
The name of the GitHub repository. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
module.exports = {
@ -231,11 +239,11 @@ module.exports = {
};
```
### `deploymentBranch` {#deploymentbranch}
### `deploymentBranch` {#deploymentBranch}
- Type: `string`
The name of the branch to deploy the static files to. Used by the deployment command.
The name of the branch to deploy the static files to. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
module.exports = {
@ -243,11 +251,11 @@ module.exports = {
};
```
### `githubHost` {#githubhost}
### `githubHost` {#githubHost}
- Type: `string`
The hostname of your server. Useful if you are using GitHub Enterprise.
The hostname of your server. Useful if you are using GitHub Enterprise. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
module.exports = {
@ -259,7 +267,7 @@ module.exports = {
- Type: `string`
The port of your server. Useful if you are using GitHub Enterprise.
The port of your server. Useful if you are using GitHub Enterprise. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
module.exports = {
@ -267,19 +275,23 @@ module.exports = {
};
```
### `themeConfig` {#themeconfig}
### `themeConfig` {#themeConfig}
- Type: `Object`
The [theme configuration](./themes/theme-configuration.md) object, to customize your site UI like navbar, footer.
The [theme configuration](./themes/theme-configuration.md) object to customize your site UI like navbar and footer.
Example:
```js title="docusaurus.config.js"
module.exports = {
themeConfig: {
hideableSidebar: false,
autoCollapseSidebarCategories: false,
docs: {
sidebar: {
hideable: false,
autoCollapseCategories: false,
},
},
colorMode: {
defaultMode: 'light',
disableSwitch: false,
@ -398,7 +410,7 @@ Attempting to add unknown fields in the config will lead to errors during build
Error: The field(s) 'foo', 'bar' are not recognized in docusaurus.config.js
```
### `staticDirectories` {#staticdirectories}
### `staticDirectories` {#staticDirectories}
An array of paths, relative to the site's directory or absolute. Files under these paths will be copied to the build output as-is.
@ -416,7 +428,7 @@ module.exports = {
An array of scripts to load. The values can be either strings or plain objects of attribute-value maps. The `<script>` tags will be inserted in the HTML `<head>`.
Note that `<script>` added here are render-blocking so you might want to add `async: true`/`defer: true` to the objects.
Note that `<script>` added here are render-blocking, so you might want to add `async: true`/`defer: true` to the objects.
- Type: `(string | Object)[]`
@ -436,9 +448,30 @@ module.exports = {
};
```
### `clientModules` {#clientmodules}
### `stylesheets` {#stylesheets}
An array of [client modules](../advanced/client.md#client-modules) to load globally on your site:
An array of CSS sources to load. The values can be either strings or plain objects of attribute-value maps. The `<link>` tags will be inserted in the HTML `<head>`.
- Type: `(string | Object)[]`
Example:
```js title="docusaurus.config.js"
module.exports = {
stylesheets: [
// String format.
'https://docusaurus.io/style.css',
// Object format.
{
href: 'http://mydomain.com/style.css',
},
],
};
```
### `clientModules` {#clientModules}
An array of [client modules](../advanced/client.md#client-modules) to load globally on your site.
Example:
@ -451,9 +484,9 @@ module.exports = {
};
```
### `ssrTemplate` {#ssrtemplate}
### `ssrTemplate` {#ssrTemplate}
An HTML template written in [Eta's syntax](https://eta.js.org/docs/syntax#syntax-overview) that will be used to render your application. This can be used to set custom attributes on the `body` tags, additional `meta` tags, customize the `viewport`, etc. Please note that Docusaurus will rely on the template to be correctly structured in order to function properly, once you do customize it, you will have to make sure that your template is compliant with the requirements from `upstream`.
An HTML template written in [Eta's syntax](https://eta.js.org/docs/syntax#syntax-overview) that will be used to render your application. This can be used to set custom attributes on the `body` tags, additional `meta` tags, customize the `viewport`, etc. Please note that Docusaurus will rely on the template to be correctly structured in order to function properly, once you do customize it, you will have to make sure that your template is compliant with the requirements from upstream.
- Type: `string`
@ -495,32 +528,11 @@ module.exports = {
};
```
### `stylesheets` {#stylesheets}
An array of CSS sources to load. The values can be either strings or plain objects of attribute-value maps. The `<link>` tags will be inserted in the HTML `<head>`.
- Type: `(string | Object)[]`
Example:
```js title="docusaurus.config.js"
module.exports = {
stylesheets: [
// String format.
'https://docusaurus.io/style.css',
// Object format.
{
href: 'http://mydomain.com/style.css',
},
],
};
```
### `titleDelimiter` {#titledelimiter}
### `titleDelimiter` {#titleDelimiter}
- Type: `string`
A string that will be used as title delimiter in the generated `<title>` tag.
Will be used as title delimiter in the generated `<title>` tag.
Example:
@ -530,7 +542,7 @@ module.exports = {
};
```
### `baseUrlIssueBanner` {#baseurlissuebanner}
### `baseUrlIssueBanner` {#baseurlIssueBanner}
- Type: `boolean`

View file

@ -0,0 +1,2 @@
label: Miscellaneous
position: 4

View file

@ -0,0 +1,74 @@
---
sidebar_position: 0
id: eslint-plugin
title: '📦 eslint-plugin'
slug: '/api/misc/@docusaurus/eslint-plugin'
---
[ESLint](https://eslint.org/) is a tool that statically analyzes your code and reports problems or suggests best practices through editor hints and command line. Docusaurus provides an ESLint plugin to enforce best Docusaurus practices.
## Installation
```bash npm2yarn
npm install --save-dev @docusaurus/eslint-plugin
```
## Usage
Add `@docusaurus` to the plugins section of your `.eslintrc` configuration file:
```json title=".eslintrc"
{
"plugins": ["@docusaurus"]
}
```
Then, you can extend one of the configs (e.g. the `recommended` config):
```json title=".eslintrc"
{
"extends": ["plugin:@docusaurus/recommended"]
}
```
Each config contains a set of rules. For more fine-grained control, you can also configure the rules you want to use directly:
```json title=".eslintrc"
{
"rules": {
"@docusaurus/string-literal-i18n-messages": "error",
"@docusaurus/no-untranslated-text": "warn"
}
}
```
## Supported Configs
- Recommended: recommended rule set for most Docusaurus sites that should be extended from.
- All: **all** rules enabled. This will change between minor versions, so you should not use this if you want to avoid unexpected breaking changes.
## Supported Rules
| Name | Description | |
| --- | --- | --- |
| [`@docusaurus/no-untranslated-text`](./no-untranslated-text.md) | Enforce text labels in JSX to be wrapped by translate calls | |
| [`@docusaurus/string-literal-i18n-messages`](./string-literal-i18n-messages.md) | Enforce translate APIs to be called on plain text labels | ✅ |
✅ = recommended
## Example configuration
Here's an example configuration:
```js title=".eslintrc.js"
module.exports = {
extends: ['plugin:@docusaurus/recommended'],
plugins: ['@docusaurus'],
rules: {
'@docusaurus/no-untranslated-text': [
'warn',
{ignoredStrings: ['·', '—', '×']},
],
},
};
```

View file

@ -0,0 +1,48 @@
---
slug: '/api/misc/@docusaurus/eslint-plugin/no-untranslated-text'
---
# no-untranslated-text
Enforce text labels in JSX to be wrapped by translate calls.
When the [i18n feature](../../../i18n/i18n-introduction.md) is used, this rule ensures that all labels appearing on the website are translatable, so no string accidentally slips through untranslated.
## Rule Details {#details}
Examples of **incorrect** code for this rule:
```js
// Hello World is not translated
<Component>Hello World</Component>
```
Examples of **correct** code for this rule:
```js
// Hello World is translated
<Component>
<Translate>Hello World</Translate>
</Component>
```
## Rule Configuration {#configuration}
Accepted fields:
<APITable>
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `ignoredStrings` | `string[]` | `[]` | Text labels that only contain strings in this list will not be reported. |
</APITable>
## When Not To Use It {#when-not-to-use}
If you're not using the [i18n feature](../../../i18n/i18n-introduction.md), you can disable this rule. You can also disable this rule where the text is not supposed to be translated.
## Further Reading {#further-reading}
- https://docusaurus.io/docs/docusaurus-core#translate
- https://docusaurus.io/docs/docusaurus-core#translate-imperative

View file

@ -0,0 +1,50 @@
---
slug: '/api/misc/@docusaurus/eslint-plugin/string-literal-i18n-messages'
---
# string-literal-i18n-messages
Enforce translate APIs to be called on plain text labels.
Docusaurus offers the [`docusaurus write-translations`](../../../cli.md#docusaurus-write-translations-sitedir) API, which statically extracts the text labels marked as translatable. Dynamic values used in `<Translate>` or `translate()` calls will fail to be extracted. This rule will ensure that all translate calls are statically extractable.
## Rule Details {#details}
Examples of **incorrect** code for this rule:
```js
const text = 'Some text to be translated'
// Invalid <Translate> child
<Translate>{text}</Translate>
// Invalid message attribute
translate({message: text})
```
Examples of **correct** code for this rule:
```js
// Valid <Translate> child
<Translate>Some text to be translated</Translate>
// Valid message attribute
translate({message: 'Some text to be translated'})
// Valid <Translate> child using values object as prop
<Translate values={{firstName: 'Sébastien'}}>
{'Welcome, {firstName}! How are you?'}
</Translate>
// Valid message attribute using values object as second argument
translate({message: 'The logo of site {siteName}'}, {siteName: 'Docusaurus'})
```
## When Not To Use It {#when-not-to-use}
If you're not using the [i18n feature](../../../i18n/i18n-introduction.md), you can disable this rule.
## Further Reading {#further-reading}
- https://docusaurus.io/docs/docusaurus-core#translate
- https://docusaurus.io/docs/docusaurus-core#translate-imperative

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View file

@ -0,0 +1,67 @@
---
sidebar_position: 1
title: '📦 logger'
slug: '/api/plugins/@docusaurus/logger'
---
An encapsulated logger for semantically formatting console messages.
Authors of packages in the Docusaurus ecosystem are encouraged to use this package to provide unified log formats.
## APIs
It exports a single object as default export: `logger`. `logger` has the following properties:
- Some useful colors.
- `red`
- `yellow`
- `green`
- `bold`
- `dim`
- Formatters. These functions all have the signature `(msg: unknown) => string`. Note that their implementations are not guaranteed. You should only care about their semantics.
- `path`: formats a file path.
- `url`: formats a URL.
- `name`: formats an identifier.
- `code`: formats a code snippet.
- `subdue`: subdues the text.
- `num`: formats a number.
- The `interpolate` function. It is a template literal tag. The syntax can be found below.
- Logging functions. All logging functions can both be used as normal functions (similar to the `console.log` family, but only accepts one parameter) or template literal tags.
- `info`: prints information.
- `warn`: prints a warning that should be payed attention to.
- `error`: prints an error (not necessarily halting the program) that signals significant problems.
- `success`: prints a success message.
:::caution A word on the `error` formatter
Beware that an `error` message, even when it doesn't hang the program, is likely going to cause confusion. When users inspect logs and find an `[ERROR]`, even when the build succeeds, they will assume something is going wrong. Use it sparingly.
Docusaurus only uses `logger.error` when printing messages immediately before throwing an error, or when user has set the reporting severity of `onBrokenLink`, etc. to `"error"`.
In addition, `warn` and `error` will color the **entire** message for better attention. If you are printing large blocks of help text about an error, better use `logger.info`.
:::
### Using the template literal tag
The template literal tag evaluates the template and expressions embedded. `interpolate` returns a new string, while other logging functions prints it. Below is a typical usage:
```js
logger.info`Hello name=${name}! You have number=${money} dollars. Here are the ${
items.length > 1 ? 'items' : 'item'
} on the shelf: ${items}
To buy anything, enter code=${'buy x'} where code=${'x'} is the item's name; to quit, press code=${'Ctrl + C'}.`;
```
An embedded expression is optionally preceded by a flag in the form `[a-z]+=` (a few lowercase letters, followed by an equals sign, directly preceding the embedded expression). If the expression is not preceded by any flag, it's printed out as-is. Otherwise, it's formatted with one of the formatters:
- `path=`: `path`
- `url=`: `url`
- `name=`: `name`
- `code=`: `code`
- `subdue=`: `subdue`
- `number=`: `num`
If the expression is an array, it's formatted by `` `\n- ${array.join('\n- ')}\n` `` (note it automatically gets a leading line end). Each member is formatted by itself and the bullet is not formatted. So you would see the above message printed as:
![demo](./img/logger-demo.png)

View file

@ -24,13 +24,13 @@ The plugin module's default export is a constructor function with the signature
`context` is plugin-agnostic, and the same object will be passed into all plugins used for a Docusaurus website. The `context` object contains the following fields:
```ts
interface LoadContext {
type LoadContext = {
siteDir: string;
generatedFilesDir: string;
siteConfig: DocusaurusConfig;
outDir: string;
baseUrl: string;
}
};
```
### `options` {#options}

View file

@ -61,7 +61,7 @@ module.exports = function (context, options) {
## `getThemePath()` {#getThemePath}
Returns the path to the directory where the theme components can be found. When your users call `swizzle`, `getThemePath` is called and its returned path is used to find your theme components.
Returns the path to the directory where the theme components can be found. When your users call `swizzle`, `getThemePath` is called and its returned path is used to find your theme components. Relative paths are resolved against the folder containing the entry point.
For example, your `getThemePath` can be:
@ -73,7 +73,7 @@ module.exports = function (context, options) {
name: 'my-theme',
// highlight-start
getThemePath() {
return path.resolve(__dirname, './theme');
return './theme';
},
// highlight-end
};
@ -103,11 +103,11 @@ module.exports = function (context, options) {
// highlight-start
getThemePath() {
// Where compiled JavaScript output lives
return path.join(__dirname, '../lib/theme');
return '../lib/theme';
},
getTypeScriptThemePath() {
// Where TypeScript source code lives
return path.resolve(__dirname, '../src/theme');
return '../src/theme';
},
// highlight-end
};

View file

@ -43,17 +43,17 @@ The data that was loaded in `loadContent` will be consumed in `contentLoaded`. I
Create a route to add to the website.
```ts
interface RouteConfig {
type RouteConfig = {
path: string;
component: string;
modules?: RouteModule;
modules?: RouteModules;
routes?: RouteConfig[];
exact?: boolean;
priority?: number;
}
interface RouteModule {
[module: string]: Module | RouteModule | RouteModule[];
}
};
type RouteModules = {
[module: string]: Module | RouteModules | RouteModules[];
};
type Module =
| {
path: string;
@ -233,6 +233,27 @@ module.exports = function (context, options) {
Read the [webpack-merge strategy doc](https://github.com/survivejs/webpack-merge#merging-with-strategies) for more details.
### Configuring dev server {#configuring-dev-server}
The dev server can be configured through returning a `devServer` field.
```js title="docusaurus-plugin/src/index.js"
module.exports = function (context, options) {
return {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
return {
// highlight-start
devServer: {
open: '/docs', // Opens localhost:3000/docs instead of localhost:3000/
},
// highlight-end
};
},
};
};
```
## `configurePostCss(options)` {#configurePostCss}
Modifies [`postcssOptions` of `postcss-loader`](https://webpack.js.org/loaders/postcss-loader/#postcssoptions) during the generation of the client bundle.
@ -318,7 +339,7 @@ function injectHtmlTags(): {
type HtmlTags = string | HtmlTagObject | (string | HtmlTagObject)[];
interface HtmlTagObject {
type HtmlTagObject = {
/**
* Attributes of the HTML tag
* E.g. `{'disabled': true, 'value': 'demo', 'rel': 'preconnect'}`
@ -334,7 +355,7 @@ interface HtmlTagObject {
* The inner HTML
*/
innerHTML?: string;
}
};
```
Example:

View file

@ -37,32 +37,32 @@ Accepted fields:
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `string` | `'blog'` | Path to the blog content directory on the filesystem, relative to site dir. |
| `editUrl` | <code>string \| EditUrlFunction</code> | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativeDocPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `path` | `string` | `'blog'` | Path to the blog content directory on the file system, relative to site dir. |
| `editUrl` | <code>string \| EditUrlFunction</code> | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativePostPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. |
| `blogTitle` | `string` | `'Blog'` | Blog page title for better SEO. |
| `blogDescription` | `string` | `'Blog'` | Blog page meta description for better SEO. |
| `blogSidebarCount` | <code>number \| 'ALL'</code> | `5` | Number of blog post elements to show in the blog sidebar. `'ALL'` to show all blog posts; `0` to disable |
| `blogSidebarCount` | <code>number \| 'ALL'</code> | `5` | Number of blog post elements to show in the blog sidebar. `'ALL'` to show all blog posts; `0` to disable. |
| `blogSidebarTitle` | `string` | `'Recent posts'` | Title of the blog sidebar. |
| `routeBasePath` | `string` | `'blog'` | URL route for the blog section of your site. **DO NOT** include a trailing slash. Use `/` to put the blog at root path. |
| `tagsBasePath` | `string` | `'tags'` | URL route for the tags list page of your site. It is prepended to the `routeBasePath`. |
| `archiveBasePath` | <code>string \| null</code> | `'/archive'` | URL route for the archive blog section of your site. It is prepended to the `routeBasePath`. **DO NOT** include a trailing slash. Use `null` to disable generation of archive. |
| `include` | `string[]` | `['**/*.{md,mdx}']` | Matching files will be included and processed. |
| `exclude` | `string[]` | _See example configuration_ | No route will be created for matching files. |
| `tagsBasePath` | `string` | `'tags'` | URL route for the tags section of your blog. Will be appended to `routeBasePath`. **DO NOT** include a trailing slash. |
| `archiveBasePath` | <code>string \| null</code> | `'archive'` | URL route for the archive section of your blog. Will be appended to `routeBasePath`. **DO NOT** include a trailing slash. Use `null` to disable generation of archive. |
| `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. |
| `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. |
| `postsPerPage` | <code>number \| 'ALL'</code> | `10` | Number of posts to show per page in the listing page. Use `'ALL'` to display all posts on one listing page. |
| `blogListComponent` | `string` | `'@theme/BlogListPage'` | Root component of the blog listing page. |
| `blogPostComponent` | `string` | `'@theme/BlogPostPage'` | Root component of each blog post page. |
| `blogTagsListComponent` | `string` | `'@theme/BlogTagsListPage'` | Root component of the tags list page |
| `blogTagsListComponent` | `string` | `'@theme/BlogTagsListPage'` | Root component of the tags list page. |
| `blogTagsPostsComponent` | `string` | `'@theme/BlogTagsPostsPage'` | Root component of the "posts containing tag" page. |
| `blogArchiveComponent` | `string` | `'@theme/BlogArchivePage'` | Root component of the blog archive page. |
| `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. |
| `rehypePlugins` | `any[]` | `[]` | Rehype plugins passed to MDX. |
| `beforeDefaultRemarkPlugins` | `any[]` | `[]` | Custom Remark plugins passed to MDX before the default Docusaurus Remark plugins. |
| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. |
| `truncateMarker` | `string` | `/<!--\s*(truncate)\s*-->/` | Truncate marker, can be a regex or string. |
| `truncateMarker` | `RegExp` | `/<!--\s*(truncate)\s*-->/` | Truncate marker marking where the summary ends. |
| `showReadingTime` | `boolean` | `true` | Show estimated reading time for the blog post. |
| `readingTime` | `ReadingTimeFunctionOption` | The default reading time | A callback to customize the reading time number displayed. |
| `authorsMapPath` | `string` | `'authors.yml'` | Path to the authors map file, relative to the blog content directory specified with `path`. Can also be a `json` file. |
| `authorsMapPath` | `string` | `'authors.yml'` | Path to the authors map file, relative to the blog content directory. |
| `feedOptions` | _See below_ | `{type: ['rss', 'atom']}` | Blog feed. |
| `feedOptions.type` | <code>FeedType \| FeedType[] \| 'all' \| null</code> | **Required** | Type of feed to be generated. Use `null` to disable generation. |
| `feedOptions.title` | `string` | `siteConfig.title` | Title of the feed. |
@ -174,7 +174,7 @@ Accepted fields:
| `title` | `string` | Markdown title | The blog post title. |
| `date` | `string` | File name or file creation time | The blog post creation date. If not specified, this can be extracted from the file or folder name, e.g, `2021-04-15-blog-post.mdx`, `2021-04-15-blog-post/index.mdx`, `2021/04/15/blog-post.mdx`. Otherwise, it is the Markdown file creation time. |
| `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your post. |
| `draft` | `boolean` | `false` | A boolean flag to indicate that the blog post is work-in-progress and therefore should not be published yet. However, draft blog posts will be displayed during development. |
| `draft` | `boolean` | `false` | A boolean flag to indicate that the blog post is work-in-progress. Draft blog posts will only be displayed during development. |
| `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. |
| `toc_min_heading_level` | `number` | `2` | The minimum heading level shown in the table of contents. Must be between 2 and 6 and lower or equal to the max value. |
| `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. |

View file

@ -31,24 +31,23 @@ Accepted fields:
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `string` | `'docs'` | Path to data on filesystem relative to site dir. |
| `breadcrumbs` | `boolean` | `true` | To enable or disable the breadcrumbs on docs pages. |
| `path` | `string` | `'docs'` | Path to the docs content directory on the file system, relative to site directory. |
| `editUrl` | <code>string \| EditUrlFunction</code> | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativeDocPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. |
| `editCurrentVersion` | `boolean` | `false` | The edit URL will always target the current version doc instead of older versions. Ignored when `editUrl` is a function. |
| `routeBasePath` | `string` | `'docs'` | URL route for the docs section of your site. **DO NOT** include a trailing slash. Use `/` for shipping docs without base path. |
| `tagsBasePath` | `string` | `'tags'` | URL route for the tags list page of your site. It is prepended to the `routeBasePath`. |
| `include` | `string[]` | `['**/*.{md,mdx}']` | Matching files will be included and processed. |
| `exclude` | `string[]` | _See example configuration_ | No route will be created for matching files. |
| `sidebarPath` | <code>false \| string</code> | `undefined` (creates autogenerated sidebar) | Path to sidebar configuration. |
| `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. |
| `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. |
| `sidebarPath` | <code>false \| string</code> | `undefined` | Path to sidebar configuration. Use `false` to disable sidebars, or `undefined` to create a fully autogenerated sidebar. |
| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar#collapsible-categories) |
| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar#expanded-categories-by-default) |
| `sidebarItemsGenerator` | `SidebarGenerator` | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` by real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) |
| `sidebarItemsGenerator` | `SidebarGenerator` | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) |
| `numberPrefixParser` | <code>boolean \| PrefixParser</code> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar#using-number-prefixes) |
| `docLayoutComponent` | `string` | `'@theme/DocPage'` | Root Layout component of each doc page. |
| `docLayoutComponent` | `string` | `'@theme/DocPage'` | Root layout component of each doc page. Provides the version data context, and is not unmounted when switching docs. |
| `docItemComponent` | `string` | `'@theme/DocItem'` | Main doc container, with TOC, pagination, etc. |
| `docTagsListComponent` | `string` | `'@theme/DocTagsListPage'` | Root component of the tags list page |
| `docTagDocListComponent` | `string` | `'@theme/DocTagDocListPage'` | Root component of the "docs containing tag" page. |
| `docTagDocListComponent` | `string` | `'@theme/DocTagDocListPage'` | Root component of the "docs containing tag X" page. |
| `docCategoryGeneratedIndexComponent` | `string` | `'@theme/DocCategoryGeneratedIndexPage'` | Root component of the generated category index page. |
| `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. |
| `rehypePlugins` | `any[]` | `[]` | Rehype plugins passed to MDX. |
@ -56,11 +55,12 @@ Accepted fields:
| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. |
| `showLastUpdateAuthor` | `boolean` | `false` | Whether to display the author who last updated the doc. |
| `showLastUpdateTime` | `boolean` | `false` | Whether to display the last date the doc was updated. |
| `disableVersioning` | `boolean` | `false` | Explicitly disable versioning even with versions. This will make the site only include the current version. |
| `breadcrumbs` | `boolean` | `true` | Enable or disable the breadcrumbs on doc pages. |
| `disableVersioning` | `boolean` | `false` | Explicitly disable versioning even when multiple versions exist. This will make the site only include the current version. Will error if `includeCurrentVersion: false` and `disableVersioning: true`. |
| `includeCurrentVersion` | `boolean` | `true` | Include the current version of your docs. |
| `lastVersion` | `string` | First version in `versions.json` | Set the version navigated to in priority and displayed by default for docs navbar items. |
| `lastVersion` | `string` | First version in `versions.json` | The version navigated to in priority and displayed by default for docs navbar items. |
| `onlyIncludeVersions` | `string[]` | All versions available | Only include a subset of all available versions. |
| `versions` | `Versions` | `{}` | Independent customization of each version's properties. |
| `versions` | `VersionsConfig` | `{}` | Independent customization of each version's properties. |
</APITable>
@ -78,38 +78,65 @@ type PrefixParser = (filename: string) => {
numberPrefix?: number;
};
type CategoryIndexMatcher = (doc: {
type CategoryIndexMatcher = (param: {
/** The file name, without extension */
fileName: string;
/**
* The list of directories, from lowest level to highest.
* If there's no dir name, directories is ['.']
*/
directories: string[];
/** The extension, with a leading dot */
extension: string;
}) => boolean;
type SidebarGenerator = (generatorArgs: {
item: {type: 'autogenerated'; dirName: string}; // the sidebar item with type "autogenerated"
version: {contentPath: string; versionName: string}; // the current version
/** The sidebar item with type "autogenerated" to be transformed. */
item: {type: 'autogenerated'; dirName: string};
/** Useful metadata for the version this sidebar belongs to. */
version: {contentPath: string; versionName: string};
/** All the docs of that version (unfiltered). */
docs: Array<{
id: string;
title: string;
frontMatter: DocFrontMatter & Record<string, unknown>;
source: string;
sourceDirName: string;
sidebarPosition?: number | undefined;
}>; // all the docs of that version (unfiltered)
numberPrefixParser: PrefixParser; // numberPrefixParser configured for this plugin
categoriesMetadata: Record<string, CategoryMetadata>; // key is the path relative to the doc directory, value is the category metadata file's content
isCategoryIndex: CategoryIndexMatcher; // the default category index matcher, that you can override
defaultSidebarItemsGenerator: SidebarGenerator; // useful to re-use/enhance default sidebar generation logic from Docusaurus
}>;
/** Number prefix parser configured for this plugin. */
numberPrefixParser: PrefixParser;
/** The default category index matcher which you can override. */
isCategoryIndex: CategoryIndexMatcher;
/**
* key is the path relative to the doc content directory, value is the
* category metadata file's content.
*/
categoriesMetadata: {[filePath: string]: CategoryMetadata};
/**
* Useful to re-use/enhance the default sidebar generation logic from
* Docusaurus.
*/
defaultSidebarItemsGenerator: SidebarGenerator;
}) => Promise<SidebarItem[]>;
type Versions = Record<
string, // the version's ID
{
label: string; // the label of the version
path: string; // the route path of the version
banner: 'none' | 'unreleased' | 'unmaintained'; // the banner to show at the top of a doc of that version
badge: boolean; // show a badge with the version name at the top of a doc of that version
className; // add a custom className to the <html> element when browsing docs of that version
}
>;
type VersionsConfig = {
[versionName: string]: {
/**
* The base path of the version, will be appended to `baseUrl` +
* `routeBasePath`.
*/
path?: string;
/** The label of the version to be used in badges, dropdowns, etc. */
label?: string;
/** The banner to show at the top of a doc of that version. */
banner?: 'none' | 'unreleased' | 'unmaintained';
/** Show a badge with the version label at the top of each doc. */
badge?: boolean;
/** Add a custom class name to the <html> element of each doc */
className?: string;
};
};
```
### Example configuration {#ex-config}
@ -235,6 +262,7 @@ Accepted fields:
| `image` | `string` | `undefined` | Cover or thumbnail image that will be used when displaying the link to your post. |
| `slug` | `string` | File path | Allows to customize the document url (`/<routeBasePath>/<slug>`). Support multiple patterns: `slug: my-doc`, `slug: /my/path/myDoc`, `slug: /`. |
| `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your docs. |
| `draft` | `boolean` | `false` | A boolean flag to indicate that a document is a work-in-progress. Draft documents will only be displayed during development. |
</APITable>

View file

@ -63,7 +63,7 @@ Most Docusaurus users configure this plugin through the preset options.
// Plugin Options: @docusaurus/plugin-google-gtag
const config = {
trackingID: '141789564',
trackingID: 'G-226F0LR9KE',
anonymizeIP: true,
};
```

View file

@ -39,6 +39,7 @@ Accepted fields:
| --- | --- | --- | --- |
| `changefreq` | `string` | `'weekly'` | See [sitemap docs](https://www.sitemaps.org/protocol.html#xmlTagDefinitions) |
| `priority` | `number` | `0.5` | See [sitemap docs](https://www.sitemaps.org/protocol.html#xmlTagDefinitions) |
| `ignorePatterns` | `string[]` | `[]` | A list of glob patterns; matching route paths will be filtered from the sitemap. Note that you may need to include the base URL in here. |
</APITable>
@ -46,8 +47,8 @@ Accepted fields:
This plugin also respects some site config:
- [`noIndex`](../docusaurus.config.js.md#noindex): results in no sitemap generated
- [`trailingSlash`](../docusaurus.config.js.md#trailing-slash): determines if the URLs in the sitemap have trailing slashes
- [`noIndex`](../docusaurus.config.js.md#noIndex): results in no sitemap generated
- [`trailingSlash`](../docusaurus.config.js.md#trailingSlash): determines if the URLs in the sitemap have trailing slashes
:::
@ -68,6 +69,7 @@ Most Docusaurus users configure this plugin through the preset options.
const config = {
changefreq: 'weekly',
priority: 0.5,
ignorePatterns: ['/tags/**'],
};
```

View file

@ -259,6 +259,7 @@ Accepted fields:
| --- | --- | --- | --- |
| `type` | `'default'` | Optional | Sets the type of this item to a link. |
| `label` | `string` | **Required** | The name to be shown for this item. |
| `html` | `string` | Optional | Same as `label`, but renders pure HTML instead of text content. |
| `to` | `string` | **Required** | Client-side routing, used for navigating within the website. The baseUrl will be automatically prepended to this value. |
| `href` | `string` | **Required** | A full-page navigation, used for navigating outside of the website. **Only one of `to` or `href` should be used.** |
| `prependBaseUrlToHref` | `boolean` | `false` | Prepends the baseUrl to `href` values. |
@ -288,6 +289,8 @@ module.exports = {
// Only one of "to" or "href" should be used
// href: 'https://www.facebook.com',
label: 'Introduction',
// Only one of "label" or "html" should be used
// html: '<b>Introduction</b>'
position: 'left',
activeBaseRegex: 'docs/(next|v8)',
target: '_blank',
@ -309,6 +312,7 @@ Navbar dropdown items only accept the following **"link-like" item types**:
- [Navbar doc link](#navbar-doc-link)
- [Navbar docs version](#navbar-docs-version)
- [Navbar doc sidebar](#navbar-doc-sidebar)
- [Navbar with custom HTML](#navbar-with-custom-html)
Note that the dropdown base item is a clickable link as well, so this item can receive any of the props of a [plain navbar link](#navbar-link).
@ -618,6 +622,39 @@ module.exports = {
};
```
#### Navbar with custom HTML {#navbar-with-custom-html}
You can also render your own HTML markup inside a navbar item using this navbar item type.
<APITable name="navbar-html">
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `type` | `'html'` | **Required** | Sets the type of this item to a HTML element. |
| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. |
| `className` | `string` | `''` | Custom CSS class for this navbar item. |
| `value` | `string` | `''` | Custom HTML to be rendered inside this navbar item. |
</APITable>
```js title="docusaurus.config.js"
module.exports = {
themeConfig: {
navbar: {
items: [
// highlight-start
{
type: 'html',
position: 'right',
value: '<button>Give feedback</button>',
},
// highlight-end
],
},
},
};
```
### Auto-hide sticky navbar {#auto-hide-sticky-navbar}
You can enable this cool UI feature that automatically hides the navbar when a user starts scrolling down the page, and show it again when the user scrolls up.
@ -663,9 +700,28 @@ Accepted fields:
| `theme` | `PrismTheme` | `palenight` | The Prism theme to use for light-theme code blocks. |
| `darkTheme` | `PrismTheme` | `palenight` | The Prism theme to use for dark-theme code blocks. |
| `defaultLanguage` | `string` | `undefined` | The side of the navbar this item should appear on. |
| `magicComments` | `MagicCommentConfig[]` | _see below_ | The list of [magic comments](../../guides/markdown-features/markdown-features-code-blocks.mdx#custom-magic-comments). |
</APITable>
```ts
type MagicCommentConfig = {
className: string;
line?: string;
block?: {start: string; end: string};
};
```
```js
const defaultMagicComments = [
{
className: 'theme-code-block-highlighted-line',
line: 'highlight-next-line',
block: {start: 'highlight-start', end: 'highlight-end'},
},
];
```
### Theme {#theme}
By default, we use [Palenight](https://github.com/FormidableLabs/prism-react-renderer/blob/master/src/themes/palenight.js) as syntax highlighting theme. You can specify a custom theme from the [list of available themes](https://github.com/FormidableLabs/prism-react-renderer/tree/master/src/themes). You may also use a different syntax highlighting theme when the site is in dark mode.
@ -901,9 +957,9 @@ import {useColorMode} from '@docusaurus/theme-common';
const Example = () => {
// highlight-next-line
const {isDarkTheme, setLightTheme, setDarkTheme} = useColorMode();
const {colorMode, setColorMode} = useColorMode();
return <h1>Dark mode is now {isDarkTheme ? 'on' : 'off'}</h1>;
return <h1>Dark mode is now {colorMode === 'dark' ? 'on' : 'off'}</h1>;
};
```

View file

@ -50,6 +50,16 @@ Please note that some functionality (for example, anchor links) will not work in
:::
:::info Development over network
When forwarding port 3000 from a remote server or VM (e.g. GitHub Codespaces), you can run the dev server on `0.0.0.0` to make it listen on the local IP.
```bash npm2yarn
npm run start -- --host 0.0.0.0
```
:::
#### Enabling HTTPS {#enabling-https}
There are multiple ways to obtain a certificate. We will use [mkcert](https://github.com/FiloSottile/mkcert) as an example.
@ -161,7 +171,7 @@ By default, the files are written in `website/i18n/<defaultLocale>/...`.
### `docusaurus write-heading-ids [siteDir] [files]` {#docusaurus-write-heading-ids-sitedir}
Add [explicit heading ids](./guides/markdown-features/markdown-features-headings.mdx#explicit-ids) to the Markdown documents of your site.
Add [explicit heading ids](./guides/markdown-features/markdown-features-toc.mdx#explicit-ids) to the Markdown documents of your site.
| Name | Default | Description |
| --- | --- | --- |

View file

@ -44,7 +44,7 @@ By default, this will load your site at [http://localhost:3000/](http://localhos
## Trailing slash configuration {#trailing-slashes}
Docusaurus has a [`trailingSlash` config](./api/docusaurus.config.js.md#trailing-slash), to allow customizing URLs/links and emitted filename patterns.
Docusaurus has a [`trailingSlash` config](./api/docusaurus.config.js.md#trailingSlash), to allow customizing URLs/links and emitted filename patterns.
The default value generally works fine. Unfortunately, each static hosting provider has a **different behavior**, and deploying the exact same site to various hosts can lead to distinct results. Depending on your host, it can be useful to change this config.
@ -56,7 +56,7 @@ Use [slorber/trailing-slash-guide](https://github.com/slorber/trailing-slash-gui
## Using environment variables {#using-environment-variables}
Putting potentially sensitive information in the environment is common practice. However, in a typical Docusaurus website, the `docusaurus.config.js` file is the only interface to the Node.js environment (see [our architecture overview](advanced/architecture.md)), while everything else—MDX pages, React components... are client side and do not have direct access to the `process` global. In this case, you can consider using [`customFields`](api/docusaurus.config.js.md#customfields) to pass environment variables to the client side.
Putting potentially sensitive information in the environment is common practice. However, in a typical Docusaurus website, the `docusaurus.config.js` file is the only interface to the Node.js environment (see [our architecture overview](advanced/architecture.md)), while everything else—MDX pages, React components... are client side and do not have direct access to the `process` global. In this case, you can consider using [`customFields`](api/docusaurus.config.js.md#customFields) to pass environment variables to the client side.
```js title="docusaurus.config.js"
// If you are using dotenv (https://www.npmjs.com/package/dotenv)

View file

@ -341,31 +341,31 @@ type PluginVersionInformation =
| {readonly type: 'local'}
| {readonly type: 'synthetic'};
interface DocusaurusSiteMetadata {
type SiteMetadata = {
readonly docusaurusVersion: string;
readonly siteVersion?: string;
readonly pluginVersions: Record<string, PluginVersionInformation>;
}
};
interface I18nLocaleConfig {
type I18nLocaleConfig = {
label: string;
direction: string;
}
};
interface I18n {
type I18n = {
defaultLocale: string;
locales: [string, ...string[]];
currentLocale: string;
localeConfigs: Record<string, I18nLocaleConfig>;
}
};
interface DocusaurusContext {
type DocusaurusContext = {
siteConfig: DocusaurusConfig;
siteMetadata: DocusaurusSiteMetadata;
siteMetadata: SiteMetadata;
globalData: Record<string, unknown>;
i18n: I18n;
codeTranslations: Record<string, string>;
}
};
```
Usage example:
@ -544,7 +544,11 @@ This is the most convenient hook to access plugin global data and should be used
`pluginId` is optional if you don't use multi-instance plugins.
```ts
function usePluginData(pluginName: string, pluginId?: string);
function usePluginData(
pluginName: string,
pluginId?: string,
options?: {failfast?: boolean},
);
```
Usage example:
@ -567,7 +571,10 @@ const MyComponent = () => {
Access global data created by a specific plugin. Given a plugin name, it returns the data of all the plugins instances of that name, by plugin id.
```ts
useAllPluginInstancesData(pluginName: string)
function useAllPluginInstancesData(
pluginName: string,
options?: {failfast?: boolean},
);
```
Usage example:
@ -614,7 +621,7 @@ import {interpolate} from '@docusaurus/Interpolate';
const message = interpolate('Welcome {firstName}', {firstName: 'Sébastien'});
```
### `translate` {#translate-1}
### `translate` {#translate-imperative}
The imperative counterpart of the [`<Translate>`](#translate) component. Also supporting [placeholders interpolation](#interpolate).

View file

@ -7,11 +7,7 @@ sidebar_label: Pages
In this section, we will learn about creating pages in Docusaurus.
This is useful for creating **one-off standalone pages** like a showcase page, playground page, or support page.
The functionality of pages is powered by `@docusaurus/plugin-content-pages`.
You can use React components, or Markdown.
The `@docusaurus/plugin-content-pages` plugin empowers you to create **one-off standalone pages** like a showcase page, playground page, or support page. You can use React components, or Markdown.
:::note
@ -35,9 +31,9 @@ Create a file `/src/pages/helloReact.js`:
import React from 'react';
import Layout from '@theme/Layout';
function Hello() {
export default function Hello() {
return (
<Layout title="Hello">
<Layout title="Hello" description="Hello React Page">
<div
style={{
display: 'flex',
@ -53,8 +49,6 @@ function Hello() {
</Layout>
);
}
export default Hello;
```
Once you save the file, the development server will automatically reload the changes. Now open `http://localhost:3000/helloReact` and you will see the new page you just created.
@ -71,7 +65,7 @@ You can also create TypeScript pages with the `.tsx` extension (`helloReact.tsx`
Create a file `/src/pages/helloMarkdown.md`:
```mdx title="/src/pages/helloMarkdown.md"
```md title="/src/pages/helloMarkdown.md"
---
title: my hello page title
description: my hello page description

View file

@ -37,17 +37,31 @@ id: part1
Lorem ipsum
```
If you want more control over the last part of the document URL, it is possible to add a `slug` (defaults to the `id`).
### Customizing doc URLs {#customizing-doc-urls}
By default, a document's URL location is its file path relative to the `docs` folder. Use the `slug` front matter to change a document's URL.
For example, suppose your site structure looks like this:
```bash
website # Root directory of your site
└── docs
└── guide
└── hello.md
```
By default `hello.md` will be available at `/docs/guide/hello`. You can change its URL location to `/docs/bonjour`:
```md
---
id: part1
slug: part1.html
slug: /bonjour
---
Lorem ipsum
```
`slug` will be appended to the doc plugin's `routeBasePath`, which is `/docs` by default. See [Docs-only mode](#docs-only-mode) for how to remove the `/docs` part from the URL.
:::note
It is possible to use:

View file

@ -307,7 +307,9 @@ function isCategoryIndex({fileName, directories}) {
For handwritten sidebar definitions, you would provide metadata to sidebar items through `sidebars.js`; for autogenerated, Docusaurus would read them from the item's respective file. In addition, you may want to adjust the relative position of each item because, by default, items within a sidebar slice will be generated in **alphabetical order** (using file and folder names).
**For docs**: use additional front matter. The `label`, `className`, and `customProps` attributes are declared in front matter as `sidebar_label`, `sidebar_class_name`, and `sidebar_custom_props`, respectively. Position can be specified in the same way, via `sidebar_position` front matter.
### Doc item metadata {#doc-item-metadata}
The `label`, `className`, and `customProps` attributes are declared in front matter as `sidebar_label`, `sidebar_class_name`, and `sidebar_custom_props`, respectively. Position can be specified in the same way, via `sidebar_position` front matter.
```md title="docs/tutorials/tutorial-easy.md"
---
@ -323,7 +325,9 @@ sidebar_class_name: green
This is the easy tutorial!
```
**For categories**: add a `_category_.json` or `_category_.yml` file in the respective folder. You can specify any category metadata and also the `position` metadata.
### Category item metadata {#category-item-metadata}
Add a `_category_.json` or `_category_.yml` file in the respective folder. You can specify any category metadata and also the `position` metadata. `label`, `className`, `position`, and `customProps` will default to the respective values of the category's linked doc, if there is one.
<Tabs>
<TabItem value="JSON">
@ -338,6 +342,9 @@ This is the easy tutorial!
"link": {
"type": "generated-index",
"title": "Tutorial overview"
},
"customProps": {
"description": "This description can be used in the swizzled DocCard"
}
}
```
@ -354,6 +361,8 @@ className: red
link:
type: generated-index
title: Tutorial overview
customProps:
description: This description can be used in the swizzled DocCard
```
</TabItem>

View file

@ -121,13 +121,17 @@ type SidebarsFile = {
### Hideable sidebar {#hideable-sidebar}
By enabling the `themeConfig.hideableSidebar` option, you can make the entire sidebar hideable, allowing users to better focus on the content. This is especially useful when content is consumed on medium-sized screens (e.g. tablets).
By enabling the `themeConfig.docs.sidebar.hideable` option, you can make the entire sidebar hideable, allowing users to better focus on the content. This is especially useful when content is consumed on medium-sized screens (e.g. tablets).
```js title="docusaurus.config.js"
module.exports = {
themeConfig: {
// highlight-start
hideableSidebar: true,
docs: {
sidebar: {
hideable: true,
},
},
// highlight-end
},
};
@ -135,13 +139,18 @@ module.exports = {
### Auto-collapse sidebar categories {#auto-collapse-sidebar-categories}
The `themeConfig.autoCollapseSidebarCategories` option would collapse all sibling categories when expanding one category. This saves the user from having too many categories open and helps them focus on the selected section.
The `themeConfig.docs.sidebar.autoCollapseCategories` option would collapse all sibling categories when expanding one category. This saves the user from having too many categories open and helps them focus on the selected section.
```js title="docusaurus.config.js"
module.exports = {
themeConfig: {
// highlight-next-line
autoCollapseSidebarCategories: true,
// highlight-start
docs: {
sidebar: {
autoCollapseCategories: true,
},
},
// highlight-end
},
};
```

View file

@ -118,6 +118,8 @@ The pagination label by default is the sidebar label. You can use the front matt
The `ref` type is identical to the [`doc` type](#sidebar-item-doc) in every way, except that it doesn't participate in generating navigation metadata. It only registers itself as a link. When [generating pagination](#generating-pagination) and [displaying sidebar](#sidebar-association), `ref` items are completely ignored.
It is particularly useful where you wish to link to the same document from multiple sidebars. The document only belongs to one sidebar (the one where it's registered as `type: 'doc'` or from an autogenerated directory), but its link will appear in all sidebars that it's registered in.
Consider this example:
```js title="sidebars.js"

View file

@ -87,14 +87,14 @@ If you use [Prettier](https://prettier.io) to format your Markdown files, Pretti
<!-- prettier-ignore -->
```md
<!-- Prettier doesn't change this -->
::: note
:::note
Hello world
:::
<!-- Prettier changes this -->
::: note
:::note
Hello world
:::

View file

@ -6,6 +6,8 @@ slug: /markdown-features/assets
---
import BrowserWindow from '@site/src/components/BrowserWindow';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Sometimes you want to link to assets (e.g. docx files, images...) directly from Markdown files, and it is convenient to co-locate the asset next to the Markdown file using it.
@ -24,12 +26,18 @@ Let's imagine the following file structure:
You can display images in three different ways: Markdown syntax, CJS require, or ES imports syntax.
<Tabs>
<TabItem value="Markdown syntax">
Display images using simple Markdown syntax:
```md
![Example banner](./assets/docusaurus-asset-example-banner.png)
```
</TabItem>
<TabItem value="CommonJS require">
Display images using inline CommonJS `require` in JSX image tag:
```jsx
@ -39,6 +47,9 @@ Display images using inline CommonJS `require` in JSX image tag:
/>
```
</TabItem>
<TabItem value="Import statement">
Display images using ES `import` syntax and JSX image tag:
```jsx
@ -47,7 +58,10 @@ import myImageUrl from './assets/docusaurus-asset-example-banner.png';
<img src={myImageUrl} alt="Example banner" />;
```
This results in displaying the image:
</TabItem>
</Tabs>
All of the above result in displaying the image:
<BrowserWindow>
@ -63,7 +77,7 @@ If you are using [@docusaurus/plugin-ideal-image](../../api/plugins/plugin-ideal
## Files {#files}
In the same way, you can link to existing assets by requiring them and using the returned url in videos, links, etc.
In the same way, you can link to existing assets by `require`'ing them and using the returned URL in `video`s, `a` anchor links, etc.
```md
# My Markdown page
@ -89,7 +103,7 @@ or
:::info markdown links are always file paths
If you use the Markdown image or link syntax, all asset paths will be resolved as file paths by Docusaurus and automatically converted to `require()` calls. You don't need to use `require()` in Markdown unless you use the JSX syntax.
If you use the Markdown image or link syntax, all asset paths will be resolved as file paths by Docusaurus and automatically converted to `require()` calls. You don't need to use `require()` in Markdown unless you use the JSX syntax, which you do have to handle yourself.
:::

View file

@ -14,11 +14,13 @@ Code blocks within documentation are super-powered 💪.
You can add a title to the code block by adding a `title` key after the language (leave a space between them).
```jsx title="/src/components/HelloCodeTitle.js"
function HelloCodeTitle(props) {
return <h1>Hello, {props.name}</h1>;
}
```
````md
```jsx title="/src/components/HelloCodeTitle.js"
function HelloCodeTitle(props) {
return <h1>Hello, {props.name}</h1>;
}
```
````
<BrowserWindow>
@ -34,9 +36,11 @@ function HelloCodeTitle(props) {
Code blocks are text blocks wrapped around by strings of 3 backticks. You may check out [this reference](https://github.com/mdx-js/specification) for the specifications of MDX.
```js
console.log('Every repo must come with a mascot.');
```
````md
```js
console.log('Every repo must come with a mascot.');
```
````
Use the matching language meta string for your code block, and Docusaurus will pick up syntax highlighting automatically, powered by [Prism React Renderer](https://github.com/FormidableLabs/prism-react-renderer).
@ -79,6 +83,12 @@ Some popular languages like Java, C#, or PHP are not enabled by default.
To add syntax highlighting for any of the other [Prism-supported languages](https://prismjs.com/#supported-languages), define it in an array of additional languages.
:::note
Each additional language has to be a valid Prism component name. For example, Prism would map the _language_ `cs` to `csharp`, but only `prism-csharp.js` exists as a _component_, so you need to use `additionalLanguages: ['csharp']`. You can look into `node_modules/prismjs/components` to find all components (languages) available.
:::
For example, if you want to add highlighting for the PowerShell language:
```js title="docusaurus.config.js"
@ -127,26 +137,28 @@ You can refer to [Prism's official language definitions](https://github.com/Pris
You can use comments with `highlight-next-line`, `highlight-start`, and `highlight-end` to select which lines are highlighted.
```js
function HighlightSomeText(highlight) {
if (highlight) {
// highlight-next-line
return 'This text is highlighted!';
}
````md
```js
function HighlightSomeText(highlight) {
if (highlight) {
// highlight-next-line
return 'This text is highlighted!';
}
return 'Nothing highlighted';
}
return 'Nothing highlighted';
}
function HighlightMoreText(highlight) {
// highlight-start
if (highlight) {
return 'This range is highlighted!';
}
// highlight-end
function HighlightMoreText(highlight) {
// highlight-start
if (highlight) {
return 'This range is highlighted!';
}
// highlight-end
return 'Nothing highlighted';
}
```
return 'Nothing highlighted';
}
```
````
````mdx-code-block
<BrowserWindow>
@ -177,50 +189,52 @@ function HighlightMoreText(highlight) {
Supported commenting syntax:
| Language | Syntax |
| Style | Syntax |
| ---------- | ------------------------ |
| JavaScript | `/* ... */` and `// ...` |
| JSX | `{/* ... */}` |
| Python | `# ...` |
| HTML | `<!-- ... -->` |
| C-style | `/* ... */` and `// ...` |
| JSX-style | `{/* ... */}` |
| Bash-style | `# ...` |
| HTML-style | `<!-- ... -->` |
If there's a syntax that is not currently supported, we are open to adding them! Pull requests welcome.
We will do our best to infer which set of comment styles to use based on the language, and default to allowing _all_ comment styles. If there's a comment style that is not currently supported, we are open to adding them! Pull requests welcome. Note that different comment styles have no semantic difference, only their content does.
To accomplish this, Docusaurus adds the `docusaurus-highlight-code-line` class to the highlighted lines. You will need to define your own styling for this CSS, possibly in your `src/css/custom.css` with a custom background color which is dependent on your selected syntax highlighting theme. The color given below works for the default highlighting theme (Palenight), so if you are using another theme, you will have to tweak the color accordingly.
You can set your own background color for highlighted code line in your `src/css/custom.css` which will better fit to your selected syntax highlighting theme. The color given below works for the default highlighting theme (Palenight), so if you are using another theme, you will have to tweak the color accordingly.
```css title="/src/css/custom.css"
.docusaurus-highlight-code-line {
background-color: rgb(72, 77, 91);
display: block;
margin: 0 calc(-1 * var(--ifm-pre-padding));
padding: 0 var(--ifm-pre-padding);
:root {
--docusaurus-highlighted-code-line-bg: rgb(72, 77, 91);
}
/* If you have a different syntax highlighting theme for dark mode. */
[data-theme='dark'] .docusaurus-highlight-code-line {
[data-theme='dark'] {
/* Color which works with dark mode syntax highlighting theme */
background-color: rgb(100, 100, 100);
--docusaurus-highlighted-code-line-bg: rgb(100, 100, 100);
}
```
If you also need to style the highlighted code line in some other way, you can target on `theme-code-block-highlighted-line` CSS class.
### Highlighting with metadata string {#highlighting-with-metadata-string}
You can also specify highlighted line ranges within the language meta string (leave a space after the language). To highlight multiple lines, separate the line numbers by commas or use the range syntax to select a chunk of lines. This feature uses the `parse-number-range` library and you can find [more syntax](https://www.npmjs.com/package/parse-numeric-range) on their project details.
```jsx {1,4-6,11}
import React from 'react';
````md
```jsx {1,4-6,11}
import React from 'react';
function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}
function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}
return <div>Foo</div>;
}
return <div>Foo</div>;
}
export default MyComponent;
```
export default MyComponent;
```
````
````mdx-code-block
<BrowserWindow>
```jsx {1,4-6,11}
@ -238,6 +252,7 @@ export default MyComponent;
```
</BrowserWindow>
````
:::tip prefer comments
@ -257,17 +272,149 @@ Prefer highlighting with comments where you can. By inlining highlight in the co
```
````
In the future, we may extend the magic comment system and let you define custom directives and their functionalities. The magic comments would only be parsed if a highlight metastring is not present.
Below, we will introduce how the magic comment system can be extended to define custom directives and their functionalities. The magic comments would only be parsed if a highlight metastring is not present.
:::
### Custom magic comments {#custom-magic-comments}
`// highlight-next-line` and `// highlight-start` etc. are called "magic comments", because they will be parsed and removed, and their purposes are to add metadata to the next line, or the section that the pair of start- and end-comments enclose.
You can declare custom magic comments through theme config. For example, you can register another magic comment that adds a `code-block-error-line` class name:
`````mdx-code-block
<Tabs>
<TabItem value="docusaurus.config.js">
```js
module.exports = {
themeConfig: {
prism: {
magicComments: [
// Remember to extend the default highlight class name as well!
{
className: 'theme-code-block-highlighted-line',
line: 'highlight-next-line',
block: {start: 'highlight-start', end: 'highlight-end'},
},
// highlight-start
{
className: 'code-block-error-line',
line: 'This will error',
},
// highlight-end
],
},
},
};
```
</TabItem>
<TabItem value="src/css/custom.css">
```css
.code-block-error-line {
background-color: #ff000020;
display: block;
margin: 0 calc(-1 * var(--ifm-pre-padding));
padding: 0 var(--ifm-pre-padding);
border-left: 3px solid #ff000080;
}
```
</TabItem>
<TabItem value="myDoc.md">
````md
In JavaScript, trying to access properties on `null` will error.
```js
const name = null;
// This will error
console.log(name.toUpperCase());
// Uncaught TypeError: Cannot read properties of null (reading 'toUpperCase')
```
````
</TabItem>
</Tabs>
`````
````mdx-code-block
<BrowserWindow>
In JavaScript, trying to access properties on `null` will error.
```js
const name = null;
// This will error
console.log(name.toUpperCase());
// Uncaught TypeError: Cannot read properties of null (reading 'toUpperCase')
```
</BrowserWindow>
````
If you use number ranges in metastring (the `{1,3-4}` syntax), Docusaurus will apply the **first `magicComments` entry**'s class name. This, by default, is `theme-code-block-highlighted-line`, but if you change the `magicComments` config and use a different entry as the first one, the meaning of the metastring range will change as well.
You can disable the default line highlighting comments with `magicComments: []`. If there's no magic comment config, but Docusaurus encounters a code block containing a metastring range, it will error because there will be no class name to apply—the highlighting class name, after all, is just a magic comment entry.
Every magic comment entry will contain three keys: `className` (required), `line`, which applies to the directly next line, or `block` (containing `start` and `end`), which applies to the entire block enclosed by the two comments.
Using CSS to target the class can already do a lot, but you can unlock the full potential of this feature through [swizzling](../../swizzling.md).
```bash npm2yarn
npm run swizzle @docusaurus/theme-classic CodeBlock/Line
```
The `Line` component will receive the list of class names, based on which you can conditionally render different markup.
## Line numbering {#line-numbering}
You can enable line numbering for your code block by using `showLineNumbers` key within the language meta string (don't forget to add space directly before the key).
````md
```jsx {1,4-6,11} showLineNumbers
import React from 'react';
function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}
return <div>Foo</div>;
}
export default MyComponent;
```
````
````mdx-code-block
<BrowserWindow>
```jsx {1,4-6,11} showLineNumbers
import React from 'react';
function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}
return <div>Foo</div>;
}
export default MyComponent;
```
</BrowserWindow>
````
## Interactive code editor {#interactive-code-editor}
(Powered by [React Live](https://github.com/FormidableLabs/react-live))
You can create an interactive coding editor with the `@docusaurus/theme-live-codeblock` plugin.
First, add the plugin to your package.
You can create an interactive coding editor with the `@docusaurus/theme-live-codeblock` plugin. First, add the plugin to your package.
```bash npm2yarn
npm install --save @docusaurus/theme-live-codeblock
@ -285,31 +432,34 @@ module.exports = {
To use the plugin, create a code block with `live` attached to the language meta string.
```jsx live
function Clock(props) {
const [date, setDate] = useState(new Date());
useEffect(() => {
var timerID = setInterval(() => tick(), 1000);
````md
```jsx live
function Clock(props) {
const [date, setDate] = useState(new Date());
useEffect(() => {
var timerID = setInterval(() => tick(), 1000);
return function cleanup() {
clearInterval(timerID);
};
});
return function cleanup() {
clearInterval(timerID);
};
});
function tick() {
setDate(new Date());
}
function tick() {
setDate(new Date());
}
return (
<div>
<h2>It is {date.toLocaleTimeString()}.</h2>
</div>
);
}
```
return (
<div>
<h2>It is {date.toLocaleTimeString()}.</h2>
</div>
);
}
```
````
The code block will be rendered as an interactive editor. Changes to the code will reflect on the result panel live.
````mdx-code-block
<BrowserWindow>
```jsx live
@ -336,6 +486,7 @@ function Clock(props) {
```
</BrowserWindow>
````
### Imports {#imports}
@ -384,6 +535,7 @@ export default ReactLiveScope;
The `ButtonExample` component is now available to use:
````mdx-code-block
<BrowserWindow>
```jsx live
@ -397,6 +549,7 @@ function MyPlayground(props) {
```
</BrowserWindow>
````
## Using JSX markup in code blocks {#using-jsx-markup}
@ -445,9 +598,9 @@ Syntax highlighting only works on plain strings. Docusaurus will not attempt to
With MDX, you can easily create interactive components within your documentation, for example, to display code in multiple programming languages and switch between them using a tabs component.
Instead of implementing a dedicated component for multi-language support code blocks, we've implemented a generic Tabs component in the classic theme so that you can use it for other non-code scenarios as well.
Instead of implementing a dedicated component for multi-language support code blocks, we've implemented a general-purpose [`<Tabs>`](./markdown-features-tabs.mdx) component in the classic theme so that you can use it for other non-code scenarios as well.
The following example is how you can have multi-language code tabs in your docs. Note that the empty lines above and below each language block are **intentional**. This is a current limitation of MDX: you have to leave empty lines around Markdown syntax for the MDX parser to know that it's Markdown syntax and not JSX.
The following example is how you can have multi-language code tabs in your docs. Note that the empty lines above and below each language block are **intentional**. This is a [current limitation of MDX](./markdown-features-react.mdx#markdown-and-jsx-interoperability): you have to leave empty lines around Markdown syntax for the MDX parser to know that it's Markdown syntax and not JSX.
````jsx
import Tabs from '@theme/Tabs';
@ -467,7 +620,7 @@ function helloWorld() {
```py
def hello_world():
print 'Hello, world!'
print("Hello, world!")
```
</TabItem>
@ -503,7 +656,7 @@ function helloWorld() {
```py
def hello_world():
print 'Hello, world!'
print("Hello, world!")
```
</TabItem>
@ -582,7 +735,10 @@ export default function MyReactPage() {
return (
<div>
{/* highlight-start */}
<CodeBlock language="jsx" title="/src/components/HelloCodeTitle.js">
<CodeBlock
language="jsx"
title="/src/components/HelloCodeTitle.js"
showLineNumbers>
{`function HelloCodeTitle(props) {
return <h1>Hello, {props.name}</h1>;
}`}
@ -594,15 +750,18 @@ export default function MyReactPage() {
```
<BrowserWindow>
<CodeBlock language="jsx" title="/src/components/HelloCodeTitle.js">
<CodeBlock
language="jsx"
title="/src/components/HelloCodeTitle.js"
showLineNumbers>
{`function HelloCodeTitle(props) {
return <h1>Hello, {props.name}</h1>;
}`}
</CodeBlock>
</BrowserWindow>
The props accepted are `language` and `title`, in the same way as you write Markdown code blocks.
The props accepted are `language`, `title` and `showLineNumbers`, in the same way as you write Markdown code blocks.
Although discouraged, you can also pass in a `metastring` prop like `metastring='{1-2} title="/src/components/HelloCodeTitle.js"'`, which is how Markdown code blocks are handled under the hood. However, we recommend you [use comments for highlighting lines](#highlighting-with-comments).
Although discouraged, you can also pass in a `metastring` prop like `metastring='{1-2} title="/src/components/HelloCodeTitle.js" showLineNumbers'`, which is how Markdown code blocks are handled under the hood. However, we recommend you [use comments for highlighting lines](#highlighting-with-comments).
As [previously stated](#using-jsx-markup), syntax highlighting is only applied when the children is a simple string.

View file

@ -0,0 +1,83 @@
---
id: head-metadata
title: Head Metadata
description: Declaring page-specific head metadata through MDX
slug: /markdown-features/head-metadata
---
# Head metadata
## Customizing head metadata {#customizing-head-metadata}
Docusaurus automatically sets useful page metadata in `<html>`, `<head>` and `<body>` for you. It is possible to add extra metadata (or override existing ones) with the `<head>` tag in Markdown files:
```md title="markdown-features-head-metadata.mdx"
---
id: head-metadata
title: Head Metadata
---
<!-- highlight-start -->
<head>
<html className="some-extra-html-class" />
<body className="other-extra-body-class" />
<title>Head Metadata customized title!</title>
<meta charSet="utf-8" />
<meta name="twitter:card" content="summary" />
<link rel="canonical" href="https://docusaurus.io/docs/markdown-features/head-metadata" />
</head>
<!-- highlight-end -->
# Head Metadata
My text
```
```mdx-code-block
<head>
<html className="some-extra-html-class" />
<body className="other-extra-body-class" />
<title>Head Metadata customized title!</title>
<meta charSet="utf-8" />
<meta name="twitter:card" content="summary" />
<link rel="canonical" href="https://docusaurus.io/docs/markdown-features/head-metadata" />
</head>
```
This `<head>` declaration has been added to the current Markdown doc as a demo. Open your browser DevTools and check how this page's metadata has been affected.
:::note
This feature is built on top of the Docusaurus [`<Head>`](./../../docusaurus-core.md#head) component. Refer to [react-helmet](https://github.com/nfl/react-helmet) for exhaustive documentation.
:::
:::tip You don't need this for regular SEO
Content plugins (e.g. docs and blog) provide front matter options like `description`, `keywords`, and `image`, which will be automatically applied to both `description` and `og:description`, while you would have to manually declare two metadata tags when using the `<head>` tag.
:::
## Markdown page description {#markdown-page-description}
The Markdown pages' description metadata may be used in more places than the head metadata. For example, the docs plugin's [generated category index](../docs/sidebar/items.md#generated-index-page) uses the description metadata for the doc cards.
By default, the description is the first content-ful line, with some efforts to convert it to plain text. For example, the following file...
```md
# Title
Main content... May contain some [links](./file.md) or **emphasis**.
```
...will have the default description "Main content... May contain some links or emphasis". However, **it's not designed to be fully functional**. Where it fails to produce reasonable descriptions, you can explicitly provide one through front matter:
```md
---
description: This description will override the default.
---
# Title
Main content... May contain some [links](./file.md) or **emphasis**.
```

View file

@ -2,7 +2,7 @@
id: introduction
title: Markdown Features
sidebar_label: Introduction
description: Docusaurus uses GitHub Flavored Markdown (GFM). Find out more about Docusaurus-specific features when writing Markdown.
description: Docusaurus uses MDX. Find out more about Docusaurus-specific features when writing Markdown.
slug: /markdown-features
---
@ -22,7 +22,7 @@ This section assumes you are using the official Docusaurus content plugins.
Markdown is a syntax that enables you to write formatted content in a readable syntax.
The [standard Markdown syntax](https://daringfireball.net/projects/markdown/syntax) is supported, and we use [MDX](https://mdxjs.com/) as the parsing engine, which can do much more than just parsing Markdown, like rendering React components inside your documents.
We use [MDX](https://mdxjs.com/) as the parsing engine, which can do much more than just parsing [standard Markdown syntax](https://daringfireball.net/projects/markdown/syntax), like rendering React components inside your documents as well.
```md
### My Doc Section
@ -35,7 +35,7 @@ Hello world message with some **bold** text, some _italic_ text, and a [link](/)
```mdx-code-block
<BrowserWindow>
<h2>My Doc Section</h2>
<h3>My Doc Section</h3>
Hello world message with some **bold** text, some _italic_ text and a [link](/)
@ -44,6 +44,18 @@ Hello world message with some **bold** text, some _italic_ text and a [link](/)
</BrowserWindow>
```
<details>
<summary>Markdown is declarative</summary>
Some may assume a 1-1 correlation between Markdown and HTML, e.g., `![Preview](/img/docusaurus.png)` will always become `<img src="/img/docusaurus.png" alt="Preview" />`, as-is. However, _that is not the case_.
The Markdown syntax `![message](url)` only declaratively tells Docusaurus that an image needs to be inserted here, but we may do other things like transforming a [file path to URL path](./markdown-features-assets.mdx#images), so the generated markup may differ from the output of other Markdown renderers, or a naïve hand-transcription to the equivalent JSX/HTML code.
In general, you should only assume the _semantics_ of the markup (` ``` ` fences become [code blocks](./markdown-features-code-blocks.mdx); `>` becomes [quotes](#quotes), etc.), but not the actual compiled output.
</details>
## Quotes {#quotes}
Markdown quotes are beautifully styled:

View file

@ -0,0 +1,52 @@
---
id: links
description: Links to other pages in Markdown
slug: /markdown-features/links
---
# Markdown links
There are two ways of adding a link to another page: through a **URL path** and a **file path**.
```md
- [URL path to another document](./installation)
- [file path to another document](./installation.md)
```
URL paths are unprocessed by Docusaurus, and you can see them as directly rendering to `<a href="./installation">`, i.e. it will be resolved according to the page's URL location, rather than its file-system location.
If you want to reference another Markdown file **included by the same plugin**, you could use the relative path of the document you want to link to. Docusaurus' Markdown loader will convert the file path to the target file's URL path (and hence remove the `.md` extension).
For example, if you are in `docs/folder/doc1.md` and you want to reference `docs/folder/doc2.md`, `docs/folder/subfolder/doc3.md` and `docs/otherFolder/doc4.md`:
```md title="docs/folder/doc1.md"
I am referencing a [document](doc2.md).
Reference to another [document in a subfolder](subfolder/doc3.md).
[Relative document](../otherFolder/doc4.md) referencing works as well.
```
Relative file paths are resolved against the current file's directory. Absolute file paths, on the other hand, are resolved relative to the **content root**, usually `docs/`, `blog/`, or [localized ones](../../i18n/i18n-tutorial.md) like `i18n/zh-Hans/plugin-content-docs/current`.
Absolute file paths can also be relative to the site directory. However, beware that links that begin with `/docs/` or `/blog/` are **not portable** as you would need to manually update them if you create new doc versions or localize them.
```md
You can write [links](/otherFolder/doc4.md) relative to the content root (`/docs/`).
You can also write [links](/docs/otherFolder/doc4.md) relative to the site directory, but it's not recommended.
```
Using relative _file_ paths (with `.md` extensions) instead of relative _URL_ links provides the following benefits:
- Links will keep working on the GitHub interface and many Markdown editors
- You can customize the files' slugs without having to update all the links
- Moving files around the folders can be tracked by your editor, and some editors may automatically update file links
- A [versioned doc](../docs/versioning.md) will link to another doc of the exact same version
- Relative URL links are very likely to break if you update the [`trailingSlash` config](../../api/docusaurus.config.js.md#trailingSlash)
:::warning
Markdown file references only work when the source and target files are processed by the same plugin instance. This is a technical limitation of our Markdown processing architecture and will be fixed in the future. If you are linking files between plugins (e.g. linking to a doc page from a blog post), you have to use URL links.
:::

View file

@ -17,9 +17,10 @@ Please read [KaTeX](https://katex.org) documentation for more details.
Write inline math equations by wrapping LaTeX equations between `$`:
```mdx
Let $f\colon[a,b] \to \R$ be Riemann integrable. Let $F\colon[a,b]\to\R$ be $F(x)=
\int_{a}^{x} f(t)\,dt$. Then $$F$$ is continuous, and at all $x$ such that $f$ is continuous at $x$, $F$ is differentiable at $x$ with $F'(x)=f(x)$.
```latex
Let $f\colon[a,b]\to\R$ be Riemann integrable. Let $F\colon[a,b]\to\R$ be
$F(x)=\int_{a}^{x} f(t)\,dt$. Then $F$ is continuous, and at all $x$ such that
$f$ is continuous at $x$, $F$ is differentiable at $x$ with $F'(x)=f(x)$.
```
<BrowserWindow>
@ -33,7 +34,7 @@ Let $f\colon[a,b] \to \R$ be Riemann integrable. Let $F\colon[a,b]\to\R$ be $F(x
For equation block or display mode, use line breaks and `$$`:
```mdx
```latex
$$
I = \int_0^{2\pi} \sin(x)\,dx
$$

View file

@ -110,6 +110,8 @@ The `@site` alias points to your website's directory, usually where the `docusau
While declaring components within Markdown is very convenient for simple cases, it becomes hard to maintain because of limited editor support, risks of parsing errors, and low reusability. Use a separate `.js` file when your component involves complex JS logic:
```jsx title="src/components/Highlight.js"
import React from 'react';
export default function Highlight({children, color}) {
return (
<span
@ -352,7 +354,7 @@ Now you can import code snippets from another file as it is:
import CodeBlock from '@theme/CodeBlock';
import MyComponentSource from '!!raw-loader!./myComponent';
<CodeBlock className="language-jsx">{MyComponentSource}</CodeBlock>
<CodeBlock language="jsx">{MyComponentSource}</CodeBlock>
```
<!-- prettier-ignore-end -->
@ -362,7 +364,7 @@ import MyComponentSource from '!!raw-loader!@site/src/pages/examples/_myComponen
<BrowserWindow>
<CodeBlock className="language-jsx">{MyComponentSource}</CodeBlock>
<CodeBlock language="jsx">{MyComponentSource}</CodeBlock>
</BrowserWindow>
```
@ -411,7 +413,7 @@ This way, you can reuse content among multiple pages and avoid duplicating mater
:::caution
The table of contents does not currently contain the imported Markdown headings. This is a technical limitation that we are trying to solve ([issue](https://github.com/facebook/docusaurus/issues/3915)).
Currently, the table of contents does not contain the imported Markdown headings. This is a technical limitation that we are trying to solve ([issue](https://github.com/facebook/docusaurus/issues/3915)).
:::
@ -420,7 +422,7 @@ The table of contents does not currently contain the imported Markdown headings.
Within the MDX page, the following variables are available as globals:
- `frontMatter`: the front matter as a record of string keys and values;
- `toc`: the table of contents, as a tree of headings. See also [Inline TOC](./markdown-features-inline-toc.mdx) for a more concrete use-case.
- `toc`: the table of contents, as a tree of headings. See also [Inline TOC](./markdown-features-toc.mdx#inline-table-of-contents) for a more concrete use-case.
- `contentTitle`: the Markdown title, which is the first `h1` heading in the Markdown text. It's `undefined` if there isn't one (e.g. title specified in the front matter).
```jsx

View file

@ -12,7 +12,7 @@ import TabItem from '@theme/TabItem';
import styles from './markdown-features-tabs-styles.module.css';
```
Docusaurus provides `<Tabs>` components that you can use thanks to [MDX](./markdown-features-react.mdx):
Docusaurus provides the `<Tabs>` component that you can use in Markdown thanks to [MDX](./markdown-features-react.mdx):
<!-- prettier-ignore-start -->
```jsx

View file

@ -0,0 +1,246 @@
---
id: toc
description: Customizing headings and table-of-contents in Markdown
slug: /markdown-features/toc
---
import BrowserWindow from '@site/src/components/BrowserWindow';
# Headings and Table of contents
## Markdown headings {#markdown-headings}
You can use regular Markdown headings.
```md
## Level 2 title
### Level 3 title
#### Level 4 title
```
Each Markdown heading will appear as a table of contents entry.
### Heading IDs {#heading-ids}
Each heading has an ID that can be automatically generated or explicitly specified. Heading IDs allow you to link to a specific document heading in Markdown or JSX:
```md
[link](#heading-id)
```
```jsx
<Link to="#heading-id">link</Link>
```
By default, Docusaurus will generate heading IDs for you, based on the heading text. For example, `### Hello World` will have id `hello-world`.
Generated IDs have **some limitations**:
- The ID might not look good
- You might want to **change or translate** the text without updating the existing ID
A special Markdown syntax lets you set an **explicit heading id**:
```md
### Hello World {#my-explicit-id}
```
:::tip
Use the **[write-heading-ids](../../cli.md#docusaurus-write-heading-ids-sitedir)** CLI command to add explicit ids to all your Markdown documents.
:::
:::caution Avoid colliding IDs
Generated heading IDs will be guaranteed to be unique on each page, but if you use custom IDs, make sure each one appears exactly once on each page, or there will be two DOM elements with the same ID, which is invalid HTML semantics, and will lead to one heading being unlinkable.
:::
## Inline table of contents {#inline-table-of-contents}
Each Markdown document displays a table of contents on the top-right corner. But it is also possible to display an inline table of contents directly inside a markdown document, thanks to MDX.
The `toc` variable is available in any MDX document and contains all the headings of an MDX document. By default, only `h2` and `h3` headings are displayed in the TOC. You can change which heading levels are visible by setting `minHeadingLevel` or `maxHeadingLevel` for individual `TOCInline` components.
<!-- prettier-ignore -->
```jsx
import TOCInline from '@theme/TOCInline';
<TOCInline toc={toc} />
```
```mdx-code-block
import TOCInline from '@theme/TOCInline';
<BrowserWindow>
<TOCInline toc={toc} />
</BrowserWindow>
```
The `toc` global is just a list of heading items:
```ts
declare const toc: Array<{
value: string;
id: string;
level: number;
}>;
```
Note that the `toc` global is a flat array, so you can easily cut out unwanted nodes or insert extra nodes, and create a new TOC tree.
<!-- prettier-ignore -->
```jsx
import TOCInline from '@theme/TOCInline';
<TOCInline
// Only show h2 and h4 headings
toc={toc.filter((node) => node.level === 2 || node.level === 4)}
minHeadingLevel={2}
// Show h4 headings in addition to the default h2 and h3 headings
maxHeadingLevel={4}
/>
```
```mdx-code-block
<BrowserWindow>
<TOCInline
toc={toc.filter((node) => node.level === 2 || node.level === 4)}
minHeadingLevel={2}
maxHeadingLevel={4}
/>
</BrowserWindow>
```
## Customizing table of contents generation {#customizing-table-of-contents-generation}
The table-of-contents is generated by parsing the Markdown source with a [Remark plugin](./markdown-features-plugins.mdx). There are known edge-cases where it generates false-positives and false-negatives.
Markdown headings within hideable areas will still show up in the TOC. For example, headings within [`Tabs`](./markdown-features-tabs.mdx) and [`details`](./markdown-features-intro.mdx#details) will not be excluded.
Non-markdown headings will not show up in the TOC. This can be used to your advantage to tackle the aforementioned issue.
```md
<details>
<summary>Some details containing headings</summary>
<h2 id="#heading-id">I'm a heading that will not show up in the TOC</h2>
Some content...
</details>
```
The ability to ergonomically insert extra headings or ignore certain headings is a work-in-progress. If this feature is important to you, please report your use-case in [this issue](https://github.com/facebook/docusaurus/issues/6201).
---
:::caution
Below is just some dummy content to have more table of contents items available on the current page.
:::
## Example Section 1 {#example-section-1}
Lorem ipsum
### Example Subsection 1 a {#example-subsection-1-a}
Lorem ipsum
#### Example subsubsection 1 a I
#### Example subsubsection 1 a II
#### Example subsubsection 1 a III
### Example Subsection 1 b {#example-subsection-1-b}
Lorem ipsum
#### Example subsubsection 1 b I
#### Example subsubsection 1 b II
#### Example subsubsection 1 b III
### Example Subsection 1 c {#example-subsection-1-c}
Lorem ipsum
#### Example subsubsection 1 c I
#### Example subsubsection 1 c II
#### Example subsubsection 1 c III
## Example Section 2 {#example-section-2}
Lorem ipsum
### Example Subsection 2 a {#example-subsection-2-a}
Lorem ipsum
#### Example subsubsection 2 a I
#### Example subsubsection 2 a II
#### Example subsubsection 2 a III
### Example Subsection 2 b {#example-subsection-2-b}
Lorem ipsum
#### Example subsubsection 2 b I
#### Example subsubsection 2 b II
#### Example subsubsection 2 b III
### Example Subsection 2 c {#example-subsection-2-c}
Lorem ipsum
#### Example subsubsection 2 c I
#### Example subsubsection 2 c II
#### Example subsubsection 2 c III
## Example Section 3 {#example-section-3}
Lorem ipsum
### Example Subsection 3 a {#example-subsection-3-a}
Lorem ipsum
#### Example subsubsection 3 a I
#### Example subsubsection 3 a II
#### Example subsubsection 3 a III
### Example Subsection 3 b {#example-subsection-3-b}
Lorem ipsum
#### Example subsubsection 3 b I
#### Example subsubsection 3 b II
#### Example subsubsection 3 b III
### Example Subsection 3 c {#example-subsection-3-c}
Lorem ipsum
#### Example subsubsection 3 c I
#### Example subsubsection 3 c II
#### Example subsubsection 3 c III

View file

@ -6,8 +6,8 @@ Congratulations! You have understood most core features of Docusaurus now. You h
- [Used the docs plugin](./docs/docs-introduction.md) to create documentation pages. This includes [configuring the sidebar](./docs/sidebar/index.md), and even [versioning](./docs/versioning.md)
- [Used the blog plugin](../blog.mdx) to create a fully featured blog
- Tried your hands on [a range of Markdown features](./markdown-features/markdown-features-intro.mdx), which are useful for all content plugins
- [Used stylesheets](../styling-layout.md) to customize your site's appearance
- [Put images and other assets](../static-assets.md) in your pages
- [Used stylesheets](../styling-layout.md) or [swizzling](../swizzling.md) to customize your site's appearance
- [Included images and other assets](../static-assets.md) in your pages
- [Added search](../search.md) to your site
- Understood how [browser support](../browser-support.md) and [SEO](../seo.md) are done through standard Docusaurus APIs
- Learned about how [individual plugins](../using-plugins.md) are installed and configured

View file

@ -214,11 +214,11 @@ The `docusaurus write-translations` command will statically analyze all React co
The `docusaurus write-translations` command only does **static analysis** of your code. It doesn't actually run your site. Therefore, dynamic messages can't be extracted, as the message is an _expression_, not a _string_:
```tsx
```jsx
const items = [
{id: 1, title: 'Hello'},
{id: 2, title: 'World'},
]
];
function ItemsList() {
return (
@ -236,11 +236,11 @@ function ItemsList() {
This still behaves correctly at runtime. However, in the future, we may provide a "no-runtime" mechanism, allowing the translations to be directly inlined in the React code through Babel transformations, instead of calling the APIs at runtime. Therefore, to be future-proof, you should always prefer statically analyzable messages. For example, we can refactor the code above to:
```tsx
```jsx
const items = [
{id: 1, title: <Translate>Hello</Translate>},
{id: 2, title: <Translate>World</Translate>},
]
];
function ItemsList() {
return (
@ -258,6 +258,52 @@ You can see the calls to the translation APIs as purely _markers_ that tell Docu
:::
#### Pluralization {#pluralization}
When you run `write-translations`, you will notice that some labels are pluralized:
```json title="i18n/en/code.json"
{
// ...
"theme.blog.post.plurals": "One post|{count} posts"
// ...
}
```
Every language will have a list of [possible plural categories](https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html). Docusaurus will arrange them in the order of `["zero", "one", "two", "few", "many", "other"]`. For example, because English (`en`) has two plural forms ("one" and "other"), the translation message has two labels separated by a pipe (`|`). For Polish (`pl`) which has three plural forms ("one", "few", and "many"), you would provide three labels in that order, joined by pipes.
You can pluralize your own code's messages as well:
```jsx
import {translate} from '@docusaurus/Translate';
import {usePluralForm} from '@docusaurus/theme-common';
function ItemsList({items}) {
// `usePluralForm` will provide the plural selector for the current locale
const {selectMessage} = usePluralForm();
// Select the appropriate pluralized label based on `items.length`
const message = selectMessage(
items.length,
translate(
{message: 'One item|{count} items'},
{count: items.length},
),
);
return (
<>
<h2>{message}</h2>
<ul>{items.map((item) => <li key={item.id}>{item.title}</li>)}<ul>
</>
);
}
```
:::note
Docusaurus uses [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules) to resolve and select plural forms. It is important to provide the right number of plural forms in the right order for `selectMessage` to work.
:::
### Translate plugin data {#translate-plugin-data}
JSON translation files are used for everything that is interspersed in your code:
@ -377,7 +423,7 @@ Generated ids are not always a good fit for localized sites, as it requires you
+ [link](#bonjour-le-monde)
```
For localized sites, it is recommended to use **[explicit heading ids](../guides/markdown-features/markdown-features-headings.mdx#explicit-ids)**.
For localized sites, it is recommended to use **[explicit heading ids](../guides/markdown-features/markdown-features-toc.mdx#explicit-ids)**.
:::

View file

@ -20,7 +20,7 @@ Use **[docusaurus.new](https://docusaurus.new)** to test Docusaurus immediately
## Requirements {#requirements}
- [Node.js](https://nodejs.org/en/download/) version >= 14 or above (which can be checked by running `node -v`). You can use [nvm](https://github.com/nvm-sh/nvm) for managing multiple Node versions on a single machine installed.
- [Node.js](https://nodejs.org/en/download/) version 14.13 or above (which can be checked by running `node -v`). You can use [nvm](https://github.com/nvm-sh/nvm) for managing multiple Node versions on a single machine installed.
- When installing Node.js, you are recommended to check all checkboxes related to dependencies.
## Scaffold project website {#scaffold-project-website}
@ -41,7 +41,7 @@ If you do not specify `name` or `template`, it will prompt you for them.
We recommend the `classic` template so that you can get started quickly, and it contains features found in Docusaurus 1. The `classic` template contains `@docusaurus/preset-classic` which includes standard documentation, a blog, custom pages, and a CSS framework (with dark mode support). You can get up and running extremely quickly with the classic template and customize things later on when you have gained more familiarity with Docusaurus.
The `template` also accepts a git repo URL or a local file path, with the latter evaluated relative to the current working directory. The repo/folder content will be copied to the site directory. If it's a git repository, you can also specify a cloning strategy. Run `npx create-docusaurus@latest --help` for more information.
The `template` also accepts a git repo URL or a local file path, with the latter evaluated relative to the current working directory. The repo/folder content will be copied to the site directory. If it's a git repository, you can also specify a cloning strategy.
You can also use the template's TypeScript variant by passing the `--typescript` flag.
@ -66,24 +66,24 @@ You can also initialize a new project using your preferred project manager:
````mdx-code-block
<Tabs>
<TabItem value="npm v6+">
<TabItem value="npm">
```bash
npm init docusaurus website classic
npm init docusaurus
```
</TabItem>
<TabItem value="yarn">
```bash
yarn create docusaurus website classic
yarn create docusaurus
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm create docusaurus website classic
pnpm create docusaurus
```
</TabItem>
@ -99,11 +99,7 @@ Docusaurus makes best efforts to select a package manager to install dependencie
npx create-docusaurus@latest my-website classic --package-manager yarn
```
If you want to skip installing dependencies, use the `--skip-install` option.
```bash
npx create-docusaurus@latest my-website classic --skip-install
```
Run `npx create-docusaurus@latest --help` for more information about all available flags.
## Project structure {#project-structure}
@ -137,10 +133,10 @@ my-website
### Project structure rundown {#project-structure-rundown}
- `/blog/` - Contains the blog Markdown files. You can delete the directory if you do not want/need a blog. More details can be found in the [blog guide](blog.mdx)
- `/docs/` - Contains the Markdown files for the docs. Customize the order of the docs sidebar in `sidebars.js`. More details can be found in the [docs guide](./guides/docs/docs-markdown-features.mdx)
- `/src/` - Non-documentation files like pages or custom React components. You don't have to strictly put your non-documentation files in here but putting them under a centralized directory makes it easier to specify in case you need to do some sort of linting/processing
- `/src/pages` - Any files within this directory will be converted into a website page. More details can be found in the [pages guide](guides/creating-pages.md)
- `/blog/` - Contains the blog Markdown files. You can delete the directory if you've disabled the blog plugin, or you can change its name after setting the `path` option. More details can be found in the [blog guide](blog.mdx)
- `/docs/` - Contains the Markdown files for the docs. Customize the order of the docs sidebar in `sidebars.js`. You can delete the directory if you've disabled the docs plugin, or you can change its name after setting the `path` option. More details can be found in the [docs guide](./guides/docs/docs-introduction.md)
- `/src/` - Non-documentation files like pages or custom React components. You don't have to strictly put your non-documentation files here, but putting them under a centralized directory makes it easier to specify in case you need to do some sort of linting/processing
- `/src/pages` - Any JSX/TSX/MDX file within this directory will be converted into a website page. More details can be found in the [pages guide](guides/creating-pages.md)
- `/static/` - Static directory. Any contents inside here will be copied into the root of the final `build` directory
- `/docusaurus.config.js` - A config file containing the site configuration. This is the equivalent of `siteConfig.js` in Docusaurus v1
- `/package.json` - A Docusaurus website is a React app. You can install and use any npm packages you like in them

View file

@ -573,7 +573,7 @@ The following code could be helpful for migration of various pages:
### Replace AUTOGENERATED_TABLE_OF_CONTENTS {#replace-autogenerated_table_of_contents}
This feature is replaced by [inline table of content](../guides/markdown-features/markdown-features-inline-toc.mdx)
This feature is replaced by [inline table of content](../guides/markdown-features/markdown-features-toc.mdx#inline-table-of-contents)
### Update Markdown syntax to be MDX-compatible {#update-markdown-syntax-to-be-mdx-compatible}

View file

@ -42,22 +42,6 @@ Similar to [global metadata](#global-metadata), Docusaurus also allows for the a
Some content...
```
```jsx title="my-react-page.jsx"
import React from 'react';
import Head from '@docusaurus/Head';
export default function page() {
return (
<Layout title="Page" description="A React page demo">
<Head>
<meta property="og:image" content="image.png" />
</Head>
{/* ... */}
</Layout>
);
}
```
Docusaurus automatically adds `description`, `title`, canonical URL links, and other useful metadata to each Markdown page. They are configurable through front matter:
```md
@ -77,6 +61,31 @@ Prefer to use front matter for fields like `description` and `keywords`: Docusau
:::
For JSX pages, you can use the Docusaurus [`<Head>`](docusaurus-core.md#head) component.
```jsx title="my-react-page.jsx"
import React from 'react';
import Layout from '@theme/Layout';
import Head from '@docusaurus/Head';
export default function page() {
return (
<Layout title="Page" description="A React page demo">
<Head>
<meta property="og:image" content="image.png" />
</Head>
{/* ... */}
</Layout>
);
}
```
:::tip
For convenience, the default theme `<Layout>` component accept `title` and `description` as props.
:::
## Static HTML generation {#static-html-generation}
Docusaurus is a static site generator—HTML files are statically generated for every URL route, which helps search engines discover your content more easily.

View file

@ -20,7 +20,7 @@ There are a few approaches/frameworks which will work, depending on your prefere
This is the most traditional way of styling that most developers (including non-front-end developers) would be familiar with. It works fine for small websites that do not have much customization.
If you're using `@docusaurus/preset-classic`, you can create your own CSS files (e.g. `/src/css/custom.css`) and import them globally by passing them as an option into the preset.
If you're using `@docusaurus/preset-classic`, you can create your own CSS files (e.g. `/src/css/custom.css`) and import them globally by passing them as an option of the classic theme.
```js title="docusaurus.config.js"
module.exports = {
@ -114,7 +114,7 @@ Alternatively, use the following tool to generate the different shades for your
### Dark Mode {#dark-mode}
In light mode, the `<html>` element has a `data-theme="light"` attribute; and in dark mode, it's `data-theme="dark"`. Therefore, you can scope your CSS to dark-mode-only by targeting `html` with a specific attribute.
In light mode, the `<html>` element has a `data-theme="light"` attribute; in dark mode, it's `data-theme="dark"`. Therefore, you can scope your CSS to dark-mode-only by targeting `html` with a specific attribute.
```css
/* Overriding root Infima variables */
@ -145,7 +145,7 @@ Docusaurus uses `996px` as the cutoff between mobile screen width and desktop. I
## CSS modules {#css-modules}
To style your components using [CSS Modules](https://github.com/css-modules/css-modules), name your stylesheet files with the `.module.css` suffix (e.g. `welcome.module.css`). webpack will load such CSS files as CSS modules and you have to reference the class names from the imported CSS module (as opposed to using plain strings). This is similar to the convention used in [Create React App](https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet).
To style your components using [CSS Modules](https://github.com/css-modules/css-modules), name your stylesheet files with the `.module.css` suffix (e.g. `welcome.module.css`). Webpack will load such CSS files as CSS modules and you have to reference the class names as properties of the imported CSS module (as opposed to using plain strings). This is similar to the convention used in [Create React App](https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet).
```css title="styles.module.css"
.main {
@ -180,7 +180,7 @@ The class names will be processed by webpack into a globally unique class name d
:::caution
This section is a work in progress. [Welcoming PRs](https://github.com/facebook/docusaurus/issues/1640).
CSS-in-JS support is a work in progress, so libs like MUI may have display quirks. [Welcoming PRs](https://github.com/facebook/docusaurus/issues/1640).
:::

View file

@ -112,11 +112,7 @@ The best IDEs (VS Code, WebStorm, IntelliJ...) will provide a nice auto-completi
By default, the Docusaurus TypeScript config does not type-check JavaScript files.
The `// @ts-check` comment ensures the config file is properly type-checked when running:
```bash npm2yarn
npm run tsc
```
The `// @ts-check` comment ensures the config file is properly type-checked when running `npx tsc`.
:::

View file

@ -29,18 +29,18 @@ module.exports = {
Docusaurus can also load plugins from your local directory, with something like the following:
```js title="docusaurus.config.js"
const path = require('path');
module.exports = {
// ...
// highlight-next-line
plugins: [path.resolve(__dirname, '/path/to/docusaurus-local-plugin')],
plugins: ['./src/plugins/docusaurus-local-plugin'],
};
```
Paths should be absolute or relative to the config file.
## Configuring plugins {#configuring-plugins}
For the most basic usage of plugins, you can provide just the plugin name or the absolute path to the plugin.
For the most basic usage of plugins, you can provide just the plugin name or the path to the plugin.
However, plugins can have options specified by wrapping the name and an options object in a two-member tuple inside your config. This style is usually called "Babel Style".
@ -114,7 +114,7 @@ At most one plugin instance can be the "default plugin instance", by omitting th
## Using themes {#using-themes}
Themes are loaded in the exact same way as plugins—the line between them is blurry. From the consumer perspective, the `themes` and `plugins` entries are interchangeable when installing and configuring a plugin. The only nuance is that themes are loaded after plugins, and it's possible for [a theme to override a plugin's default theme components](./swizzling.md#theme-aliases).
Themes are loaded in the exact same way as plugins. From the consumer perspective, the `themes` and `plugins` entries are interchangeable when installing and configuring a plugin. The only nuance is that themes are loaded after plugins, and it's possible for [a theme to override a plugin's default theme components](./swizzling.md#theme-aliases).
:::tip
@ -132,101 +132,23 @@ module.exports = {
## Using presets {#using-presets}
A preset is usually an npm package, so you install them like other npm packages using npm.
```bash npm2yarn
npm install --save @docusaurus/preset-classic
```
Then, add it in your site's `docusaurus.config.js`'s `presets` option:
```js title="docusaurus.config.js"
module.exports = {
// ...
// highlight-next-line
presets: ['@docusaurus/preset-classic'],
};
```
To load presets from your local directory, specify how to resolve them:
```js title="docusaurus.config.js"
const path = require('path');
module.exports = {
// ...
// highlight-next-line
presets: [path.resolve(__dirname, '/path/to/docusaurus-local-preset')],
};
```
Presets are a shorthand function to add plugins and themes to your Docusaurus config. For example, you can specify a preset that includes the following themes and plugins:
```js title="/path/to/docusaurus-local-preset"
module.exports = function preset(context, opts = {}) {
return {
themes: [['docusaurus-theme-awesome', opts.theme]],
plugins: [
// Using three docs plugins at the same time!
// Assigning a unique ID for each without asking the user to do it
['@docusaurus/plugin-content-docs', {...opts.docs1, id: 'docs1'}],
['@docusaurus/plugin-content-docs', {...opts.docs2, id: 'docs2'}],
['@docusaurus/plugin-content-docs', {...opts.docs3, id: 'docs3'}],
],
};
};
```
then in your Docusaurus config, you may configure the preset instead:
```js title="docusaurus.config.js"
module.exports = {
presets: [
// highlight-start
[
path.resolve(__dirname, '/path/to/docusaurus-local-preset'),
{
theme: {hello: 'world'},
docs1: {path: '/docs'},
docs2: {path: '/community'},
docs3: {path: '/api'},
},
],
// highlight-end
],
};
```
This is equivalent of doing:
```js title="docusaurus.config.js"
module.exports = {
themes: [['docusaurus-theme-awesome', {hello: 'world'}]],
plugins: [
['@docusaurus/plugin-content-docs', {id: 'docs1', path: '/docs'}],
['@docusaurus/plugin-content-docs', {id: 'docs2', path: '/community'}],
['@docusaurus/plugin-content-docs', {id: 'docs3', path: '/api'}],
],
};
```
This is especially useful when some plugins and themes are intended to be used together. You can even link their options together, e.g. pass one option to multiple plugins.
Presets are bundles of plugins and themes. For example, instead of letting you register and configure `@docusaurus/plugin-content-docs`, `@docusaurus/plugin-content-blog`, etc. one after the other in the config file, we have `@docusaurus/preset-classic` preset allows you to configure them in one centralized place.
### `@docusaurus/preset-classic` {#docusauruspreset-classic}
The classic preset is shipped by default to new Docusaurus website created with [`create-docusaurus`](./installation.md#scaffold-project-website). It is a set of plugins and themes.
The classic preset is shipped by default to new Docusaurus websites created with [`create-docusaurus`](./installation.md#scaffold-project-website). It contains the following themes and plugins:
| Themes | Plugins |
| --- | --- |
| [`@docusaurus/theme-classic`](./api/themes/theme-configuration.md) | [`@docusaurus/plugin-content-docs`](./api/plugins/plugin-content-docs.md) |
| [`@docusaurus/theme-search-algolia`](./api/themes/theme-search-algolia.md) | [`@docusaurus/plugin-content-blog`](./api/plugins/plugin-content-blog.md) |
| | [`@docusaurus/plugin-content-pages`](./api/plugins/plugin-content-pages.md) |
| | [`@docusaurus/plugin-debug`](./api/plugins/plugin-debug.md) |
| | [`@docusaurus/plugin-google-analytics`](./api/plugins/plugin-google-analytics.md) |
| | [`@docusaurus/plugin-google-gtag`](./api/plugins/plugin-google-gtag.md) |
| | [`@docusaurus/plugin-sitemap`](./api/plugins/plugin-sitemap.md) |
- [`@docusaurus/theme-classic`](./api/themes/theme-configuration.md)
- [`@docusaurus/theme-search-algolia`](./api/themes/theme-search-algolia.md)
- [`@docusaurus/plugin-content-docs`](./api/plugins/plugin-content-docs.md)
- [`@docusaurus/plugin-content-blog`](./api/plugins/plugin-content-blog.md)
- [`@docusaurus/plugin-content-pages`](./api/plugins/plugin-content-pages.md)
- [`@docusaurus/plugin-debug`](./api/plugins/plugin-debug.md)
- [`@docusaurus/plugin-google-analytics`](./api/plugins/plugin-google-analytics.md)
- [`@docusaurus/plugin-google-gtag`](./api/plugins/plugin-google-gtag.md)
- [`@docusaurus/plugin-sitemap`](./api/plugins/plugin-sitemap.md)
To specify plugin options individually, you can provide the necessary fields to certain plugins, i.e. `customCss` for `@docusaurus/theme-classic`, pass them in the preset field, like this:
The classic preset will relay each option entry to the respective plugin/theme.
```js title="docusaurus.config.js"
module.exports = {
@ -278,13 +200,95 @@ module.exports = {
};
```
### Installing presets {#installing-presets}
A preset is usually an npm package, so you install them like other npm packages using npm.
```bash npm2yarn
npm install --save @docusaurus/preset-classic
```
Then, add it in your site's `docusaurus.config.js`'s `presets` option:
```js title="docusaurus.config.js"
module.exports = {
// ...
// highlight-next-line
presets: ['@docusaurus/preset-classic'],
};
```
Preset paths can be relative to the config file:
```js title="docusaurus.config.js"
module.exports = {
// ...
// highlight-next-line
presets: ['./src/presets/docusaurus-local-preset')],
};
```
### Creating presets {#creating-presets}
A preset is a function with the same shape as the [plugin constructor](./api/plugin-methods/README.md#plugin-constructor). It should return an object of `{ plugins: PluginConfig[], themes: PluginConfig[] }`, in the same as how they are accepted in the site config. For example, you can specify a preset that includes the following themes and plugins:
```js title="src/presets/docusaurus-preset-multi-docs.js"
module.exports = function preset(context, opts = {}) {
return {
themes: [['docusaurus-theme-awesome', opts.theme]],
plugins: [
// Using three docs plugins at the same time!
// Assigning a unique ID for each without asking the user to do it
['@docusaurus/plugin-content-docs', {...opts.docs1, id: 'docs1'}],
['@docusaurus/plugin-content-docs', {...opts.docs2, id: 'docs2'}],
['@docusaurus/plugin-content-docs', {...opts.docs3, id: 'docs3'}],
],
};
};
```
Then in your Docusaurus config, you may configure the preset:
```js title="docusaurus.config.js"
module.exports = {
presets: [
// highlight-start
[
'./src/presets/docusaurus-preset-multi-docs.js',
{
theme: {hello: 'world'},
docs1: {path: '/docs'},
docs2: {path: '/community'},
docs3: {path: '/api'},
},
],
// highlight-end
],
};
```
This is equivalent of doing:
```js title="docusaurus.config.js"
module.exports = {
themes: [['docusaurus-theme-awesome', {hello: 'world'}]],
plugins: [
['@docusaurus/plugin-content-docs', {id: 'docs1', path: '/docs'}],
['@docusaurus/plugin-content-docs', {id: 'docs2', path: '/community'}],
['@docusaurus/plugin-content-docs', {id: 'docs3', path: '/api'}],
],
};
```
This is especially useful when some plugins and themes are intended to be used together. You can even link their options together, e.g. pass one option to multiple plugins.
## Module shorthands {#module-shorthands}
Docusaurus supports shorthands for plugins, themes, and presets. When it sees a plugin / theme / preset name, it tries to load one of the following, in that order:
Docusaurus supports shorthands for plugins, themes, and presets. When it sees a plugin/theme/preset name, it tries to load one of the following, in that order:
- `[name]`
- `@docusaurus/[moduleType]-[name]`
- `docusaurus-[moduleType]-[name]`,
- `[name]` (like `content-docs`)
- `@docusaurus/[moduleType]-[name]` (like `@docusaurus/plugin-content-docs`)
- `docusaurus-[moduleType]-[name]` (like `docusaurus-plugin-content-docs`)
where `moduleType` is one of `'preset'`, `'theme'`, `'plugin'`, depending on which field the module name is declared in. The first module name that's successfully found is loaded.
@ -304,10 +308,10 @@ If the name is scoped (beginning with `@`), the name is first split into scope a
scope name
```
If the name is not specified, `{scope}/docusaurus-{type}` is loaded. Otherwise, the following are attempted:
If there is no name (like `@jquery`), `[scope]/docusaurus-[moduleType]` (i.e. `@jquery/docusaurus-plugin`) is loaded. Otherwise, the following are attempted:
- `[scope]/[name]`
- `[scope]/docusaurus-[moduleType]-[name]`
- `[scope]/[name]` (like `@jquery/content-docs`)
- `[scope]/docusaurus-[moduleType]-[name]` (like `@jquery/docusaurus-plugin-content-docs`)
Below are some examples, for a plugin registered in the `plugins` field. Note that unlike [ESLint](https://eslint.org/docs/user-guide/configuring/plugins#configuring-plugins) or [Babel](https://babeljs.io/docs/en/options#name-normalization) where a consistent naming convention for plugins is mandated, Docusaurus permits greater naming freedom, so the resolutions are not certain, but follows the priority defined above.