mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
feat(core): support TypeScript + ESM configuration (#9317)
Co-authored-by: Joshua Chen <sidachen2003@gmail.com> Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
336a44f3ea
commit
45f1a669b5
126 changed files with 2054 additions and 914 deletions
|
@ -157,17 +157,6 @@ async function copyTemplate(
|
|||
): Promise<void> {
|
||||
await fs.copy(path.join(templatesDir, 'shared'), dest);
|
||||
|
||||
// TypeScript variants will copy duplicate resources like CSS & config from
|
||||
// base template
|
||||
if (typescript) {
|
||||
await fs.copy(template.path, dest, {
|
||||
filter: async (filePath) =>
|
||||
(await fs.stat(filePath)).isDirectory() ||
|
||||
path.extname(filePath) === '.css' ||
|
||||
path.basename(filePath) === 'docusaurus.config.js',
|
||||
});
|
||||
}
|
||||
|
||||
await fs.copy(typescript ? template.tsVariantPath! : template.path, dest, {
|
||||
// Symlinks don't exist in published npm packages anymore, so this is only
|
||||
// to prevent errors during local testing
|
||||
|
|
133
packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts
vendored
Normal file
133
packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
import {themes as prismThemes} from 'prism-react-renderer';
|
||||
import type {Config} from '@docusaurus/types';
|
||||
import type * as Preset from '@docusaurus/preset-classic';
|
||||
|
||||
const config: Config = {
|
||||
title: 'My Site',
|
||||
tagline: 'Dinosaurs are cool',
|
||||
favicon: 'img/favicon.ico',
|
||||
|
||||
// Set the production url of your site here
|
||||
url: 'https://your-docusaurus-site.example.com',
|
||||
// Set the /<baseUrl>/ pathname under which your site is served
|
||||
// For GitHub pages deployment, it is often '/<projectName>/'
|
||||
baseUrl: '/',
|
||||
|
||||
// GitHub pages deployment config.
|
||||
// If you aren't using GitHub pages, you don't need these.
|
||||
organizationName: 'facebook', // Usually your GitHub org/user name.
|
||||
projectName: 'docusaurus', // Usually your repo name.
|
||||
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
|
||||
// Even if you don't use internationalization, you can use this field to set
|
||||
// useful metadata like html lang. For example, if your site is Chinese, you
|
||||
// may want to replace "en" with "zh-Hans".
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
{
|
||||
docs: {
|
||||
sidebarPath: './sidebars.ts',
|
||||
// Please change this to your repo.
|
||||
// Remove this to remove the "edit this page" links.
|
||||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
|
||||
},
|
||||
blog: {
|
||||
showReadingTime: true,
|
||||
// Please change this to your repo.
|
||||
// Remove this to remove the "edit this page" links.
|
||||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
|
||||
},
|
||||
theme: {
|
||||
customCss: './src/css/custom.css',
|
||||
},
|
||||
} satisfies Preset.Options,
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
// Replace with your project's social card
|
||||
image: 'img/docusaurus-social-card.jpg',
|
||||
navbar: {
|
||||
title: 'My Site',
|
||||
logo: {
|
||||
alt: 'My Site Logo',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
type: 'docSidebar',
|
||||
sidebarId: 'tutorialSidebar',
|
||||
position: 'left',
|
||||
label: 'Tutorial',
|
||||
},
|
||||
{to: '/blog', label: 'Blog', position: 'left'},
|
||||
{
|
||||
href: 'https://github.com/facebook/docusaurus',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Docs',
|
||||
items: [
|
||||
{
|
||||
label: 'Tutorial',
|
||||
to: '/docs/intro',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'Stack Overflow',
|
||||
href: 'https://stackoverflow.com/questions/tagged/docusaurus',
|
||||
},
|
||||
{
|
||||
label: 'Discord',
|
||||
href: 'https://discordapp.com/invite/docusaurus',
|
||||
},
|
||||
{
|
||||
label: 'Twitter',
|
||||
href: 'https://twitter.com/docusaurus',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: 'Blog',
|
||||
to: '/blog',
|
||||
},
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/facebook/docusaurus',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Copyright © ${new Date().getFullYear()} My Project, Inc. Built with Docusaurus.`,
|
||||
},
|
||||
prism: {
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.dracula,
|
||||
},
|
||||
} satisfies Preset.ThemeConfig,
|
||||
};
|
||||
|
||||
export default config;
|
|
@ -26,6 +26,7 @@
|
|||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.0.0-beta.0",
|
||||
"@docusaurus/tsconfig": "3.0.0-beta.0",
|
||||
"@docusaurus/types": "3.0.0-beta.0",
|
||||
"typescript": "~5.2.2"
|
||||
},
|
||||
"browserslist": {
|
||||
|
|
31
packages/create-docusaurus/templates/classic-typescript/sidebars.ts
vendored
Normal file
31
packages/create-docusaurus/templates/classic-typescript/sidebars.ts
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
|
||||
|
||||
/**
|
||||
* Creating a sidebar enables you to:
|
||||
- create an ordered group of docs
|
||||
- render a sidebar for each doc of that group
|
||||
- provide next/previous navigation
|
||||
|
||||
The sidebars can be generated from the filesystem, or explicitly defined here.
|
||||
|
||||
Create as many sidebars as you want.
|
||||
*/
|
||||
const sidebars: SidebarsConfig = {
|
||||
// By default, Docusaurus generates a sidebar from the docs folder structure
|
||||
tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
|
||||
|
||||
// But you can create a sidebar manually
|
||||
/*
|
||||
tutorialSidebar: [
|
||||
'intro',
|
||||
'hello',
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Tutorial',
|
||||
items: ['tutorial-basics/create-a-document'],
|
||||
},
|
||||
],
|
||||
*/
|
||||
};
|
||||
|
||||
export default sidebars;
|
|
@ -1 +0,0 @@
|
|||
../../../../classic/src/components/HomepageFeatures/styles.module.css
|
|
@ -1 +0,0 @@
|
|||
../../../classic/src/pages/index.module.css
|
|
@ -4,10 +4,7 @@
|
|||
// There are various equivalent ways to declare your Docusaurus config.
|
||||
// See: https://docusaurus.io/docs/api/docusaurus-config
|
||||
|
||||
const {themes} = require('prism-react-renderer');
|
||||
|
||||
const lightCodeTheme = themes.github;
|
||||
const darkCodeTheme = themes.dracula;
|
||||
import {themes as prismThemes} from 'prism-react-renderer';
|
||||
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
const config = {
|
||||
|
@ -43,7 +40,7 @@ const config = {
|
|||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
({
|
||||
docs: {
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
sidebarPath: './sidebars.js',
|
||||
// Please change this to your repo.
|
||||
// Remove this to remove the "edit this page" links.
|
||||
editUrl:
|
||||
|
@ -57,7 +54,7 @@ const config = {
|
|||
'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
|
||||
},
|
||||
theme: {
|
||||
customCss: require.resolve('./src/css/custom.css'),
|
||||
customCss: './src/css/custom.css',
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
@ -135,10 +132,10 @@ const config = {
|
|||
copyright: `Copyright © ${new Date().getFullYear()} My Project, Inc. Built with Docusaurus.`,
|
||||
},
|
||||
prism: {
|
||||
theme: lightCodeTheme,
|
||||
darkTheme: darkCodeTheme,
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.dracula,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
export default config;
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
"react-dom": "^18.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.0.0-beta.0"
|
||||
"@docusaurus/module-type-aliases": "3.0.0-beta.0",
|
||||
"@docusaurus/types": "3.0.0-beta.0"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
|
|
@ -30,4 +30,4 @@ const sidebars = {
|
|||
*/
|
||||
};
|
||||
|
||||
module.exports = sidebars;
|
||||
export default sidebars;
|
|
@ -42,7 +42,7 @@ This is my **first Docusaurus document**!
|
|||
It is also possible to create your sidebar explicitly in `sidebars.js`:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
tutorialSidebar: [
|
||||
'intro',
|
||||
// highlight-next-line
|
||||
|
|
|
@ -28,7 +28,7 @@ To navigate seamlessly across versions, add a version dropdown.
|
|||
Modify the `docusaurus.config.js` file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
|
|
@ -11,7 +11,7 @@ Let's translate `docs/intro.md` to French.
|
|||
Modify `docusaurus.config.js` to add support for the `fr` locale:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'fr'],
|
||||
|
@ -54,7 +54,7 @@ To navigate seamlessly across languages, add a locale dropdown.
|
|||
Modify the `docusaurus.config.js` file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
"@types/react-router-config": "^5.0.7",
|
||||
"combine-promises": "^1.1.0",
|
||||
"fs-extra": "^11.1.1",
|
||||
"import-fresh": "^3.3.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"tslib": "^2.6.0",
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
readVersionsFile,
|
||||
} from './versions/files';
|
||||
import {validateVersionName} from './versions/validation';
|
||||
import {loadSidebarsFileUnsafe} from './sidebars';
|
||||
import {loadSidebarsFile} from './sidebars';
|
||||
import {CURRENT_VERSION_NAME} from './constants';
|
||||
import type {PluginOptions} from '@docusaurus/plugin-content-docs';
|
||||
import type {LoadContext} from '@docusaurus/types';
|
||||
|
@ -37,7 +37,7 @@ async function createVersionedSidebarFile({
|
|||
// Note: we don't need the sidebars file to be normalized: it's ok to let
|
||||
// plugin option changes to impact older, versioned sidebars
|
||||
// We don't validate here, assuming the user has already built the version
|
||||
const sidebars = await loadSidebarsFileUnsafe(sidebarPath);
|
||||
const sidebars = await loadSidebarsFile(sidebarPath);
|
||||
|
||||
// Do not create a useless versioned sidebars file if sidebars file is empty
|
||||
// or sidebars are disabled/false)
|
||||
|
|
|
@ -9,10 +9,9 @@ import fs from 'fs-extra';
|
|||
import path from 'path';
|
||||
import _ from 'lodash';
|
||||
import logger from '@docusaurus/logger';
|
||||
import {Globby} from '@docusaurus/utils';
|
||||
import {loadFreshModule, Globby} from '@docusaurus/utils';
|
||||
import Yaml from 'js-yaml';
|
||||
import combinePromises from 'combine-promises';
|
||||
import importFresh from 'import-fresh';
|
||||
import {validateSidebars, validateCategoryMetadataFile} from './validation';
|
||||
import {normalizeSidebars} from './normalization';
|
||||
import {processSidebars} from './processor';
|
||||
|
@ -68,7 +67,7 @@ async function readCategoriesMetadata(contentPath: string) {
|
|||
);
|
||||
}
|
||||
|
||||
export async function loadSidebarsFileUnsafe(
|
||||
async function loadSidebarsFileUnsafe(
|
||||
sidebarFilePath: string | false | undefined,
|
||||
): Promise<SidebarsConfig> {
|
||||
// false => no sidebars
|
||||
|
@ -89,7 +88,19 @@ export async function loadSidebarsFileUnsafe(
|
|||
}
|
||||
|
||||
// We don't want sidebars to be cached because of hot reloading.
|
||||
return importFresh(sidebarFilePath);
|
||||
const module = await loadFreshModule(sidebarFilePath);
|
||||
|
||||
// TODO unsafe, need to refactor and improve validation
|
||||
return module as SidebarsConfig;
|
||||
}
|
||||
|
||||
export async function loadSidebarsFile(
|
||||
sidebarFilePath: string | false | undefined,
|
||||
): Promise<SidebarsConfig> {
|
||||
const sidebars = await loadSidebarsFileUnsafe(sidebarFilePath);
|
||||
|
||||
// TODO unsafe, need to refactor and improve validation
|
||||
return sidebars as SidebarsConfig;
|
||||
}
|
||||
|
||||
export async function loadSidebars(
|
||||
|
|
|
@ -47,6 +47,8 @@ declare module '@docusaurus/plugin-ideal-image' {
|
|||
*/
|
||||
disableInDev?: boolean;
|
||||
};
|
||||
|
||||
export type Options = Partial<PluginOptions>;
|
||||
}
|
||||
|
||||
declare module '@theme/IdealImage' {
|
||||
|
|
1
packages/docusaurus-types/src/index.d.ts
vendored
1
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -52,6 +52,7 @@ export {
|
|||
PluginVersionInformation,
|
||||
Preset,
|
||||
PresetConfig,
|
||||
PresetConfigDefined,
|
||||
PresetModule,
|
||||
OptionValidationContext,
|
||||
ThemeConfigValidationContext,
|
||||
|
|
8
packages/docusaurus-types/src/plugin.d.ts
vendored
8
packages/docusaurus-types/src/plugin.d.ts
vendored
|
@ -26,11 +26,9 @@ export type PluginConfig =
|
|||
| false
|
||||
| null;
|
||||
|
||||
export type PresetConfig =
|
||||
| string
|
||||
| [string, {[key: string]: unknown}]
|
||||
| false
|
||||
| null;
|
||||
export type PresetConfigDefined = string | [string, {[key: string]: unknown}];
|
||||
|
||||
export type PresetConfig = PresetConfigDefined | false | null;
|
||||
|
||||
/**
|
||||
* - `type: 'package'`, plugin is in a different package.
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"github-slugger": "^1.5.0",
|
||||
"globby": "^11.1.0",
|
||||
"gray-matter": "^4.0.3",
|
||||
"jiti": "^1.20.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"micromatch": "^4.0.5",
|
||||
|
@ -44,7 +45,8 @@
|
|||
"@types/github-slugger": "^1.3.0",
|
||||
"@types/micromatch": "^4.0.2",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"dedent": "^0.7.0"
|
||||
"dedent": "^0.7.0",
|
||||
"tmp-promise": "^3.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@docusaurus/types": "*"
|
||||
|
|
7
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.cjs
generated
Normal file
7
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.cjs
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
exports.someNamedExport = 42;
|
||||
|
||||
module.exports = {
|
||||
firstName: 'Sebastien',
|
||||
lastName: 'Lorber',
|
||||
birthYear: 1986,
|
||||
};
|
7
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.cjs.js
generated
Normal file
7
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.cjs.js
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
exports.someNamedExport = 42;
|
||||
|
||||
module.exports = {
|
||||
firstName: 'Sebastien',
|
||||
lastName: 'Lorber',
|
||||
birthYear: 1986,
|
||||
};
|
11
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.cjs.ts
generated
Normal file
11
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.cjs.ts
generated
Normal file
|
@ -0,0 +1,11 @@
|
|||
exports.someNamedExport = 42 as number;
|
||||
|
||||
module.exports = {
|
||||
firstName: 'Sebastien',
|
||||
lastName: 'Lorber',
|
||||
birthYear: 1986,
|
||||
} satisfies {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
birthYear: number;
|
||||
};
|
7
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.esm.js
generated
Normal file
7
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.esm.js
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
export const someNamedExport = 42;
|
||||
|
||||
export default {
|
||||
firstName: 'Sebastien',
|
||||
lastName: 'Lorber',
|
||||
birthYear: 1986,
|
||||
};
|
11
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.esm.ts
generated
Normal file
11
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.esm.ts
generated
Normal file
|
@ -0,0 +1,11 @@
|
|||
export const someNamedExport: number = 42;
|
||||
|
||||
export default {
|
||||
firstName: 'Sebastien',
|
||||
lastName: 'Lorber',
|
||||
birthYear: 1986,
|
||||
} satisfies {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
birthYear: number;
|
||||
};
|
7
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.mjs
generated
Normal file
7
packages/docusaurus-utils/src/__tests__/__fixtures__/moduleUtils/user/user.mjs
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
export const someNamedExport = 42;
|
||||
|
||||
export default {
|
||||
firstName: 'Sebastien',
|
||||
lastName: 'Lorber',
|
||||
birthYear: 1986,
|
||||
};
|
289
packages/docusaurus-utils/src/__tests__/moduleUtils.test.ts
Normal file
289
packages/docusaurus-utils/src/__tests__/moduleUtils.test.ts
Normal file
|
@ -0,0 +1,289 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import tmp from 'tmp-promise';
|
||||
import dedent from 'dedent';
|
||||
import {loadFreshModule} from '../moduleUtils';
|
||||
|
||||
async function createTmpDir() {
|
||||
return (
|
||||
await tmp.dir({
|
||||
prefix: 'jest-tmp-moduleUtils-tests',
|
||||
})
|
||||
).path;
|
||||
}
|
||||
|
||||
async function moduleGraphHelpers() {
|
||||
const dir = await createTmpDir();
|
||||
|
||||
async function fileHelper(name: string, initialContent?: string) {
|
||||
const filePath = path.resolve(dir, name);
|
||||
if (initialContent) {
|
||||
await fs.outputFile(filePath, initialContent);
|
||||
}
|
||||
return {
|
||||
filePath,
|
||||
write: (content: string) => fs.outputFile(filePath, content),
|
||||
load: () => loadFreshModule(filePath),
|
||||
};
|
||||
}
|
||||
|
||||
return {fileHelper};
|
||||
}
|
||||
|
||||
async function loadFixtureModule(fixtureName: string) {
|
||||
return loadFreshModule(
|
||||
path.resolve(__dirname, '__fixtures__/moduleUtils', fixtureName),
|
||||
);
|
||||
}
|
||||
|
||||
describe('loadFreshModule', () => {
|
||||
describe('can load CJS user module', () => {
|
||||
async function testUserFixture(fixtureName: string) {
|
||||
const userFixturePath = `user/${fixtureName}`;
|
||||
const userModule = await loadFixtureModule(userFixturePath);
|
||||
expect(userModule).toEqual({
|
||||
birthYear: 1986,
|
||||
firstName: 'Sebastien',
|
||||
lastName: 'Lorber',
|
||||
});
|
||||
}
|
||||
|
||||
it('for .cjs.js', async () => {
|
||||
await testUserFixture('user.cjs.js');
|
||||
});
|
||||
|
||||
it('for .cjs.ts', async () => {
|
||||
await testUserFixture('user.cjs.ts');
|
||||
});
|
||||
|
||||
it('for .cjs', async () => {
|
||||
await testUserFixture('user.cjs');
|
||||
});
|
||||
});
|
||||
|
||||
describe('can load ESM user module', () => {
|
||||
async function testUserFixture(fixtureName: string) {
|
||||
const userFixturePath = `user/${fixtureName}`;
|
||||
const userModule = await loadFixtureModule(userFixturePath);
|
||||
expect(userModule).toEqual({
|
||||
birthYear: 1986,
|
||||
firstName: 'Sebastien',
|
||||
lastName: 'Lorber',
|
||||
someNamedExport: 42,
|
||||
});
|
||||
}
|
||||
|
||||
it('for .esm.js', async () => {
|
||||
await testUserFixture('user.esm.js');
|
||||
});
|
||||
|
||||
it('for .esm.ts', async () => {
|
||||
await testUserFixture('user.esm.ts');
|
||||
});
|
||||
|
||||
it('for .mjs', async () => {
|
||||
await testUserFixture('user.mjs');
|
||||
});
|
||||
});
|
||||
|
||||
describe('module graph', () => {
|
||||
it('can load and reload fresh module graph', async () => {
|
||||
const {fileHelper} = await moduleGraphHelpers();
|
||||
|
||||
const dependency1 = await fileHelper(
|
||||
'dependency1.js',
|
||||
/* language=js */
|
||||
dedent`
|
||||
export const dep1Export = "dep1 val1";
|
||||
|
||||
export default {dep1Val: "dep1 val2"}
|
||||
`,
|
||||
);
|
||||
|
||||
const dependency2 = await fileHelper(
|
||||
'dependency2.ts',
|
||||
/* language=ts */
|
||||
dedent`
|
||||
export default {dep2Val: "dep2 val"} satisfies {dep2Val: string}
|
||||
`,
|
||||
);
|
||||
|
||||
const entryFile = await fileHelper(
|
||||
'entry.js',
|
||||
/* language=js */
|
||||
dedent`
|
||||
import dependency1 from "./dependency1";
|
||||
import dependency2 from "./dependency2";
|
||||
|
||||
export default {
|
||||
someEntryValue: "entryVal",
|
||||
dependency1,
|
||||
dependency2
|
||||
};
|
||||
`,
|
||||
);
|
||||
|
||||
// Should be able to read the initial module graph
|
||||
await expect(entryFile.load()).resolves.toEqual({
|
||||
someEntryValue: 'entryVal',
|
||||
dependency1: {
|
||||
dep1Export: 'dep1 val1',
|
||||
dep1Val: 'dep1 val2',
|
||||
},
|
||||
dependency2: {
|
||||
dep2Val: 'dep2 val',
|
||||
},
|
||||
});
|
||||
await expect(dependency1.load()).resolves.toEqual({
|
||||
dep1Export: 'dep1 val1',
|
||||
dep1Val: 'dep1 val2',
|
||||
});
|
||||
await expect(dependency2.load()).resolves.toEqual({
|
||||
dep2Val: 'dep2 val',
|
||||
});
|
||||
|
||||
// Should be able to read the module graph again after updates
|
||||
await dependency1.write(
|
||||
/* language=js */
|
||||
dedent`
|
||||
export const dep1Export = "dep1 val1 updated";
|
||||
|
||||
export default {dep1Val: "dep1 val2 updated"}
|
||||
`,
|
||||
);
|
||||
await expect(entryFile.load()).resolves.toEqual({
|
||||
someEntryValue: 'entryVal',
|
||||
dependency1: {
|
||||
dep1Export: 'dep1 val1 updated',
|
||||
dep1Val: 'dep1 val2 updated',
|
||||
},
|
||||
dependency2: {
|
||||
dep2Val: 'dep2 val',
|
||||
},
|
||||
});
|
||||
await expect(dependency1.load()).resolves.toEqual({
|
||||
dep1Export: 'dep1 val1 updated',
|
||||
dep1Val: 'dep1 val2 updated',
|
||||
});
|
||||
await expect(dependency2.load()).resolves.toEqual({
|
||||
dep2Val: 'dep2 val',
|
||||
});
|
||||
|
||||
// Should be able to read the module graph again after updates
|
||||
await dependency2.write(
|
||||
/* language=ts */
|
||||
dedent`
|
||||
export default {dep2Val: "dep2 val updated"} satisfies {dep2Val: string}
|
||||
`,
|
||||
);
|
||||
await expect(entryFile.load()).resolves.toEqual({
|
||||
someEntryValue: 'entryVal',
|
||||
dependency1: {
|
||||
dep1Export: 'dep1 val1 updated',
|
||||
dep1Val: 'dep1 val2 updated',
|
||||
},
|
||||
dependency2: {
|
||||
dep2Val: 'dep2 val updated',
|
||||
},
|
||||
});
|
||||
await expect(dependency1.load()).resolves.toEqual({
|
||||
dep1Export: 'dep1 val1 updated',
|
||||
dep1Val: 'dep1 val2 updated',
|
||||
});
|
||||
await expect(dependency2.load()).resolves.toEqual({
|
||||
dep2Val: 'dep2 val updated',
|
||||
});
|
||||
|
||||
// Should be able to read the module graph again after updates
|
||||
await entryFile.write(
|
||||
/* language=js */
|
||||
dedent`
|
||||
import dependency1 from "./dependency1";
|
||||
import dependency2 from "./dependency2";
|
||||
|
||||
export default {
|
||||
someEntryValue: "entryVal updated",
|
||||
dependency1,
|
||||
dependency2,
|
||||
newAttribute: "is there"
|
||||
}
|
||||
`,
|
||||
);
|
||||
await expect(entryFile.load()).resolves.toEqual({
|
||||
someEntryValue: 'entryVal updated',
|
||||
newAttribute: 'is there',
|
||||
dependency1: {
|
||||
dep1Export: 'dep1 val1 updated',
|
||||
dep1Val: 'dep1 val2 updated',
|
||||
},
|
||||
dependency2: {
|
||||
dep2Val: 'dep2 val updated',
|
||||
},
|
||||
});
|
||||
await expect(dependency1.load()).resolves.toEqual({
|
||||
dep1Export: 'dep1 val1 updated',
|
||||
dep1Val: 'dep1 val2 updated',
|
||||
});
|
||||
await expect(dependency2.load()).resolves.toEqual({
|
||||
dep2Val: 'dep2 val updated',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('invalid module path param', () => {
|
||||
it('throws if module path does not exist', async () => {
|
||||
await expect(() => loadFreshModule('/some/unknown/module/path.js'))
|
||||
.rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Docusaurus could not load module at path "/some/unknown/module/path.js"
|
||||
Cause: Cannot find module '/some/unknown/module/path.js' from 'packages/docusaurus-utils/src/moduleUtils.ts'"
|
||||
`);
|
||||
});
|
||||
|
||||
it('throws if module path is undefined', async () => {
|
||||
await expect(() =>
|
||||
// @ts-expect-error: undefined is invalid
|
||||
loadFreshModule(undefined),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Docusaurus could not load module at path "undefined"
|
||||
Cause: Invalid module path of type undefined"
|
||||
`);
|
||||
});
|
||||
|
||||
it('throws if module path is null', async () => {
|
||||
await expect(() =>
|
||||
// @ts-expect-error: null is invalid
|
||||
loadFreshModule(null),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Docusaurus could not load module at path "null"
|
||||
Cause: Invalid module path of type null"
|
||||
`);
|
||||
});
|
||||
|
||||
it('throws if module path is number', async () => {
|
||||
await expect(() =>
|
||||
// @ts-expect-error: number is invalid
|
||||
loadFreshModule(42),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Docusaurus could not load module at path "42"
|
||||
Cause: Invalid module path of type 42"
|
||||
`);
|
||||
});
|
||||
|
||||
it('throws if module path is object', async () => {
|
||||
await expect(() =>
|
||||
// @ts-expect-error: object is invalid
|
||||
loadFreshModule({}),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Docusaurus could not load module at path "[object Object]"
|
||||
Cause: Invalid module path of type [object Object]"
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -100,6 +100,7 @@ export {
|
|||
} from './globUtils';
|
||||
export {getFileLoaderUtils} from './webpackUtils';
|
||||
export {escapeShellArg} from './shellUtils';
|
||||
export {loadFreshModule} from './moduleUtils';
|
||||
export {
|
||||
getDataFilePath,
|
||||
getDataFileData,
|
||||
|
|
43
packages/docusaurus-utils/src/moduleUtils.ts
Normal file
43
packages/docusaurus-utils/src/moduleUtils.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import jiti from 'jiti';
|
||||
import logger from '@docusaurus/logger';
|
||||
|
||||
/*
|
||||
jiti is able to load ESM, CJS, JSON, TS modules
|
||||
*/
|
||||
export async function loadFreshModule(modulePath: string): Promise<unknown> {
|
||||
try {
|
||||
if (typeof modulePath !== 'string') {
|
||||
throw new Error(
|
||||
logger.interpolate`Invalid module path of type name=${modulePath}`,
|
||||
);
|
||||
}
|
||||
const load = jiti(__filename, {
|
||||
// Transpilation cache, can be safely enabled
|
||||
cache: true,
|
||||
// Bypass Node.js runtime require cache
|
||||
// Same as "import-fresh" package we used previously
|
||||
requireCache: false,
|
||||
// Only take into consideration the default export
|
||||
// For now we don't need named exports
|
||||
// This also helps normalize return value for both CJS/ESM/TS modules
|
||||
interopDefault: true,
|
||||
// debug: true,
|
||||
});
|
||||
|
||||
return load(modulePath);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
logger.interpolate`Docusaurus could not load module at path path=${modulePath}\nCause: ${
|
||||
(error as Error).message
|
||||
}`,
|
||||
{cause: error},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -76,7 +76,6 @@
|
|||
"html-minifier-terser": "^7.2.0",
|
||||
"html-tags": "^3.3.1",
|
||||
"html-webpack-plugin": "^5.5.3",
|
||||
"import-fresh": "^3.3.0",
|
||||
"leven": "^3.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mini-css-extract-plugin": "^2.7.6",
|
||||
|
|
12
packages/docusaurus/src/server/__tests__/__fixtures__/config/configCJS.js
generated
Normal file
12
packages/docusaurus/src/server/__tests__/__fixtures__/config/configCJS.js
generated
Normal file
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
title: 'title',
|
||||
url: 'https://example.com',
|
||||
baseUrl: '/',
|
||||
}
|
14
packages/docusaurus/src/server/__tests__/__fixtures__/config/configCJS.ts
generated
Normal file
14
packages/docusaurus/src/server/__tests__/__fixtures__/config/configCJS.ts
generated
Normal file
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import type {Config} from '@docusaurus/types';
|
||||
|
||||
module.exports = {
|
||||
title: 'title',
|
||||
url: 'https://example.com',
|
||||
baseUrl: '/',
|
||||
} satisfies Config;
|
12
packages/docusaurus/src/server/__tests__/__fixtures__/config/configESM.js
generated
Normal file
12
packages/docusaurus/src/server/__tests__/__fixtures__/config/configESM.js
generated
Normal file
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
export default {
|
||||
title: 'title',
|
||||
url: 'https://example.com',
|
||||
baseUrl: '/',
|
||||
}
|
14
packages/docusaurus/src/server/__tests__/__fixtures__/config/configESM.ts
generated
Normal file
14
packages/docusaurus/src/server/__tests__/__fixtures__/config/configESM.ts
generated
Normal file
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import type {Config} from '@docusaurus/types';
|
||||
|
||||
export default {
|
||||
title: 'title',
|
||||
url: 'https://example.com',
|
||||
baseUrl: '/',
|
||||
} satisfies Config;
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
export default {
|
||||
title: 'JS title',
|
||||
url: 'https://example.com',
|
||||
baseUrl: '/',
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import type {Config} from '@docusaurus/types';
|
||||
|
||||
export default {
|
||||
title: 'TS title',
|
||||
url: 'https://example.com',
|
||||
baseUrl: '/',
|
||||
} satisfies Config;
|
|
@ -48,6 +48,246 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = `
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`loadSiteConfig website with ts + js config 1`] = `
|
||||
{
|
||||
"siteConfig": {
|
||||
"baseUrl": "/",
|
||||
"baseUrlIssueBanner": true,
|
||||
"clientModules": [],
|
||||
"customFields": {},
|
||||
"headTags": [],
|
||||
"i18n": {
|
||||
"defaultLocale": "en",
|
||||
"localeConfigs": {},
|
||||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"markdown": {
|
||||
"format": "mdx",
|
||||
"mdx1Compat": {
|
||||
"admonitions": true,
|
||||
"comments": true,
|
||||
"headingIds": true,
|
||||
},
|
||||
"mermaid": false,
|
||||
"preprocessor": undefined,
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
"onBrokenMarkdownLinks": "warn",
|
||||
"onDuplicateRoutes": "warn",
|
||||
"plugins": [],
|
||||
"presets": [],
|
||||
"scripts": [],
|
||||
"staticDirectories": [
|
||||
"static",
|
||||
],
|
||||
"stylesheets": [],
|
||||
"tagline": "",
|
||||
"themeConfig": {},
|
||||
"themes": [],
|
||||
"title": "TS title",
|
||||
"titleDelimiter": "|",
|
||||
"url": "https://example.com",
|
||||
},
|
||||
"siteConfigPath": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/config/sites/ts-and-js-site/docusaurus.config.ts",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadSiteConfig website with valid JS CJS config 1`] = `
|
||||
{
|
||||
"siteConfig": {
|
||||
"baseUrl": "/",
|
||||
"baseUrlIssueBanner": true,
|
||||
"clientModules": [],
|
||||
"customFields": {},
|
||||
"headTags": [],
|
||||
"i18n": {
|
||||
"defaultLocale": "en",
|
||||
"localeConfigs": {},
|
||||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"markdown": {
|
||||
"format": "mdx",
|
||||
"mdx1Compat": {
|
||||
"admonitions": true,
|
||||
"comments": true,
|
||||
"headingIds": true,
|
||||
},
|
||||
"mermaid": false,
|
||||
"preprocessor": undefined,
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
"onBrokenMarkdownLinks": "warn",
|
||||
"onDuplicateRoutes": "warn",
|
||||
"plugins": [],
|
||||
"presets": [],
|
||||
"scripts": [],
|
||||
"staticDirectories": [
|
||||
"static",
|
||||
],
|
||||
"stylesheets": [],
|
||||
"tagline": "",
|
||||
"themeConfig": {},
|
||||
"themes": [],
|
||||
"title": "title",
|
||||
"titleDelimiter": "|",
|
||||
"url": "https://example.com",
|
||||
},
|
||||
"siteConfigPath": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/config/configCJS.js",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadSiteConfig website with valid JS ESM config 1`] = `
|
||||
{
|
||||
"siteConfig": {
|
||||
"baseUrl": "/",
|
||||
"baseUrlIssueBanner": true,
|
||||
"clientModules": [],
|
||||
"customFields": {},
|
||||
"headTags": [],
|
||||
"i18n": {
|
||||
"defaultLocale": "en",
|
||||
"localeConfigs": {},
|
||||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"markdown": {
|
||||
"format": "mdx",
|
||||
"mdx1Compat": {
|
||||
"admonitions": true,
|
||||
"comments": true,
|
||||
"headingIds": true,
|
||||
},
|
||||
"mermaid": false,
|
||||
"preprocessor": undefined,
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
"onBrokenMarkdownLinks": "warn",
|
||||
"onDuplicateRoutes": "warn",
|
||||
"plugins": [],
|
||||
"presets": [],
|
||||
"scripts": [],
|
||||
"staticDirectories": [
|
||||
"static",
|
||||
],
|
||||
"stylesheets": [],
|
||||
"tagline": "",
|
||||
"themeConfig": {},
|
||||
"themes": [],
|
||||
"title": "title",
|
||||
"titleDelimiter": "|",
|
||||
"url": "https://example.com",
|
||||
},
|
||||
"siteConfigPath": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/config/configESM.js",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = `
|
||||
{
|
||||
"siteConfig": {
|
||||
"baseUrl": "/",
|
||||
"baseUrlIssueBanner": true,
|
||||
"clientModules": [],
|
||||
"customFields": {},
|
||||
"headTags": [],
|
||||
"i18n": {
|
||||
"defaultLocale": "en",
|
||||
"localeConfigs": {},
|
||||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"markdown": {
|
||||
"format": "mdx",
|
||||
"mdx1Compat": {
|
||||
"admonitions": true,
|
||||
"comments": true,
|
||||
"headingIds": true,
|
||||
},
|
||||
"mermaid": false,
|
||||
"preprocessor": undefined,
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
"onBrokenMarkdownLinks": "warn",
|
||||
"onDuplicateRoutes": "warn",
|
||||
"plugins": [],
|
||||
"presets": [],
|
||||
"scripts": [],
|
||||
"staticDirectories": [
|
||||
"static",
|
||||
],
|
||||
"stylesheets": [],
|
||||
"tagline": "",
|
||||
"themeConfig": {},
|
||||
"themes": [],
|
||||
"title": "title",
|
||||
"titleDelimiter": "|",
|
||||
"url": "https://example.com",
|
||||
},
|
||||
"siteConfigPath": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/config/configCJS.ts",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = `
|
||||
{
|
||||
"siteConfig": {
|
||||
"baseUrl": "/",
|
||||
"baseUrlIssueBanner": true,
|
||||
"clientModules": [],
|
||||
"customFields": {},
|
||||
"headTags": [],
|
||||
"i18n": {
|
||||
"defaultLocale": "en",
|
||||
"localeConfigs": {},
|
||||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"markdown": {
|
||||
"format": "mdx",
|
||||
"mdx1Compat": {
|
||||
"admonitions": true,
|
||||
"comments": true,
|
||||
"headingIds": true,
|
||||
},
|
||||
"mermaid": false,
|
||||
"preprocessor": undefined,
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
"onBrokenMarkdownLinks": "warn",
|
||||
"onDuplicateRoutes": "warn",
|
||||
"plugins": [],
|
||||
"presets": [],
|
||||
"scripts": [],
|
||||
"staticDirectories": [
|
||||
"static",
|
||||
],
|
||||
"stylesheets": [],
|
||||
"tagline": "",
|
||||
"themeConfig": {},
|
||||
"themes": [],
|
||||
"title": "title",
|
||||
"titleDelimiter": "|",
|
||||
"url": "https://example.com",
|
||||
},
|
||||
"siteConfigPath": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/config/configESM.ts",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadSiteConfig website with valid async config 1`] = `
|
||||
{
|
||||
"siteConfig": {
|
||||
|
|
|
@ -19,6 +19,20 @@ describe('loadSiteConfig', () => {
|
|||
expect(config).not.toEqual({});
|
||||
});
|
||||
|
||||
it('website with ts + js config', async () => {
|
||||
const config = await loadSiteConfig({
|
||||
siteDir: path.join(
|
||||
__dirname,
|
||||
'__fixtures__',
|
||||
'config/sites/ts-and-js-site',
|
||||
),
|
||||
});
|
||||
expect(config).toMatchSnapshot();
|
||||
// Docusaurus uses in priority a TS config
|
||||
expect(config.siteConfig.title).toBe('TS title');
|
||||
expect(config).not.toEqual({});
|
||||
});
|
||||
|
||||
it('website with .cjs siteConfig', async () => {
|
||||
const config = await loadSiteConfig({siteDir});
|
||||
expect(config).toMatchSnapshot();
|
||||
|
@ -52,6 +66,42 @@ describe('loadSiteConfig', () => {
|
|||
expect(config).not.toEqual({});
|
||||
});
|
||||
|
||||
it('website with valid JS CJS config', async () => {
|
||||
const config = await loadSiteConfig({
|
||||
siteDir,
|
||||
customConfigFilePath: 'configCJS.js',
|
||||
});
|
||||
expect(config).toMatchSnapshot();
|
||||
expect(config).not.toEqual({});
|
||||
});
|
||||
|
||||
it('website with valid JS ESM config', async () => {
|
||||
const config = await loadSiteConfig({
|
||||
siteDir,
|
||||
customConfigFilePath: 'configESM.js',
|
||||
});
|
||||
expect(config).toMatchSnapshot();
|
||||
expect(config).not.toEqual({});
|
||||
});
|
||||
|
||||
it('website with valid TypeScript CJS config', async () => {
|
||||
const config = await loadSiteConfig({
|
||||
siteDir,
|
||||
customConfigFilePath: 'configCJS.ts',
|
||||
});
|
||||
expect(config).toMatchSnapshot();
|
||||
expect(config).not.toEqual({});
|
||||
});
|
||||
|
||||
it('website with valid TypeScript ESM config', async () => {
|
||||
const config = await loadSiteConfig({
|
||||
siteDir,
|
||||
customConfigFilePath: 'configESM.ts',
|
||||
});
|
||||
expect(config).toMatchSnapshot();
|
||||
expect(config).not.toEqual({});
|
||||
});
|
||||
|
||||
it('website with incomplete siteConfig', async () => {
|
||||
await expect(
|
||||
loadSiteConfig({
|
||||
|
|
|
@ -7,15 +7,18 @@
|
|||
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import importFresh from 'import-fresh';
|
||||
import logger from '@docusaurus/logger';
|
||||
import {DEFAULT_CONFIG_FILE_NAME, findAsyncSequential} from '@docusaurus/utils';
|
||||
import {
|
||||
DEFAULT_CONFIG_FILE_NAME,
|
||||
findAsyncSequential,
|
||||
loadFreshModule,
|
||||
} from '@docusaurus/utils';
|
||||
import {validateConfig} from './configValidation';
|
||||
import type {LoadContext} from '@docusaurus/types';
|
||||
|
||||
async function findConfig(siteDir: string) {
|
||||
// We could support .mjs, .ts, etc. in the future
|
||||
const candidates = ['.js', '.cjs'].map(
|
||||
const candidates = ['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs'].map(
|
||||
(ext) => DEFAULT_CONFIG_FILE_NAME + ext,
|
||||
);
|
||||
const configPath = await findAsyncSequential(
|
||||
|
@ -46,7 +49,7 @@ export async function loadSiteConfig({
|
|||
throw new Error(`Config file at "${siteConfigPath}" not found.`);
|
||||
}
|
||||
|
||||
const importedConfig = importFresh(siteConfigPath);
|
||||
const importedConfig = await loadFreshModule(siteConfigPath);
|
||||
|
||||
const loadedConfig: unknown =
|
||||
typeof importedConfig === 'function'
|
||||
|
|
15
packages/docusaurus/src/server/plugins/__tests__/__fixtures__/presets/preset-plugins.esm.js
generated
Normal file
15
packages/docusaurus/src/server/plugins/__tests__/__fixtures__/presets/preset-plugins.esm.js
generated
Normal file
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
export default function preset(context, opts = {}) {
|
||||
return {
|
||||
plugins: [
|
||||
['@docusaurus/plugin-content-docs', opts.docs],
|
||||
['@docusaurus/plugin-content-blog', opts.blog],
|
||||
],
|
||||
};
|
||||
}
|
18
packages/docusaurus/src/server/plugins/__tests__/__fixtures__/presets/preset-plugins.ts
generated
Normal file
18
packages/docusaurus/src/server/plugins/__tests__/__fixtures__/presets/preset-plugins.ts
generated
Normal file
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {LoadContext, Preset} from '@docusaurus/types';
|
||||
|
||||
export default function preset(
|
||||
context: LoadContext,
|
||||
opts: {theme: {}; test: {}},
|
||||
) {
|
||||
return {
|
||||
themes: [['@docusaurus/theme-classic', opts.theme], null],
|
||||
plugins: [['@docusaurus/plugin-test', opts.theme], false],
|
||||
} satisfies Preset;
|
||||
}
|
|
@ -23,8 +23,8 @@ module.exports = {
|
|||
],
|
||||
'./plugin3.js',
|
||||
['./plugin4.js', {}],
|
||||
'./pluginEsm',
|
||||
'./pluginTypeScript',
|
||||
],
|
||||
presets: [
|
||||
'./preset.js',
|
||||
],
|
||||
presets: ['./preset.js'],
|
||||
};
|
||||
|
|
11
packages/docusaurus/src/server/plugins/__tests__/__fixtures__/site-with-plugin/pluginEsm.js
generated
Normal file
11
packages/docusaurus/src/server/plugins/__tests__/__fixtures__/site-with-plugin/pluginEsm.js
generated
Normal file
|
@ -0,0 +1,11 @@
|
|||
import {Joi} from '@docusaurus/utils-validation';
|
||||
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'plugin-esm',
|
||||
};
|
||||
}
|
||||
|
||||
export function validateThemeConfig({validate, themeConfig}) {
|
||||
return {esmPlugin: {joi: !!Joi}};
|
||||
}
|
14
packages/docusaurus/src/server/plugins/__tests__/__fixtures__/site-with-plugin/pluginTypeScript.ts
generated
Normal file
14
packages/docusaurus/src/server/plugins/__tests__/__fixtures__/site-with-plugin/pluginTypeScript.ts
generated
Normal file
|
@ -0,0 +1,14 @@
|
|||
import {Joi} from '@docusaurus/utils-validation';
|
||||
import {LoadContext, ThemeConfigValidationContext} from '@docusaurus/types';
|
||||
export default function (context: LoadContext, options: unknown) {
|
||||
return {
|
||||
name: 'plugin-ts',
|
||||
};
|
||||
}
|
||||
|
||||
export function validateThemeConfig({
|
||||
validate,
|
||||
themeConfig,
|
||||
}: ThemeConfigValidationContext<unknown, unknown>) {
|
||||
return {tsPlugin: {joi: !!Joi}};
|
||||
}
|
|
@ -63,6 +63,38 @@ exports[`loadPresets array form with options 1`] = `
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`loadPresets cjs form 1`] = `
|
||||
{
|
||||
"plugins": [
|
||||
[
|
||||
"@docusaurus/plugin-content-docs",
|
||||
undefined,
|
||||
],
|
||||
[
|
||||
"@docusaurus/plugin-content-blog",
|
||||
undefined,
|
||||
],
|
||||
],
|
||||
"themes": [],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadPresets esm form 1`] = `
|
||||
{
|
||||
"plugins": [
|
||||
[
|
||||
"@docusaurus/plugin-content-docs",
|
||||
undefined,
|
||||
],
|
||||
[
|
||||
"@docusaurus/plugin-content-blog",
|
||||
undefined,
|
||||
],
|
||||
],
|
||||
"themes": [],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadPresets mixed form 1`] = `
|
||||
{
|
||||
"plugins": [
|
||||
|
@ -127,22 +159,6 @@ exports[`loadPresets mixed form with themes 1`] = `
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`loadPresets string form 1`] = `
|
||||
{
|
||||
"plugins": [
|
||||
[
|
||||
"@docusaurus/plugin-content-docs",
|
||||
undefined,
|
||||
],
|
||||
[
|
||||
"@docusaurus/plugin-content-blog",
|
||||
undefined,
|
||||
],
|
||||
],
|
||||
"themes": [],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadPresets string form composite 1`] = `
|
||||
{
|
||||
"plugins": [
|
||||
|
@ -167,3 +183,22 @@ exports[`loadPresets string form composite 1`] = `
|
|||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadPresets ts form 1`] = `
|
||||
{
|
||||
"plugins": [
|
||||
[
|
||||
"@docusaurus/plugin-test",
|
||||
undefined,
|
||||
],
|
||||
false,
|
||||
],
|
||||
"themes": [
|
||||
[
|
||||
"@docusaurus/theme-classic",
|
||||
undefined,
|
||||
],
|
||||
null,
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -21,8 +21,8 @@ describe('initPlugins', () => {
|
|||
|
||||
it('parses plugins correctly and loads them in correct order', async () => {
|
||||
const {context, plugins} = await loadSite();
|
||||
expect(context.siteConfig.plugins).toHaveLength(4);
|
||||
expect(plugins).toHaveLength(8);
|
||||
expect(context.siteConfig.plugins).toHaveLength(6);
|
||||
expect(plugins).toHaveLength(10);
|
||||
|
||||
expect(plugins[0]!.name).toBe('preset-plugin1');
|
||||
expect(plugins[1]!.name).toBe('preset-plugin2');
|
||||
|
@ -32,7 +32,15 @@ describe('initPlugins', () => {
|
|||
expect(plugins[5]!.name).toBe('second-plugin');
|
||||
expect(plugins[6]!.name).toBe('third-plugin');
|
||||
expect(plugins[7]!.name).toBe('fourth-plugin');
|
||||
expect(context.siteConfig.themeConfig).toEqual({a: 1});
|
||||
expect(context.siteConfig.themeConfig).toEqual({
|
||||
a: 1,
|
||||
esmPlugin: {
|
||||
joi: true,
|
||||
},
|
||||
tsPlugin: {
|
||||
joi: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('throws user-friendly error message for plugins with bad values', async () => {
|
||||
|
|
|
@ -26,12 +26,38 @@ describe('loadPresets', () => {
|
|||
`);
|
||||
});
|
||||
|
||||
it('string form', async () => {
|
||||
it('cjs form', async () => {
|
||||
const context = {
|
||||
siteConfigPath: __dirname,
|
||||
siteConfig: {
|
||||
presets: [
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.js'),
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.cjs.js'),
|
||||
],
|
||||
},
|
||||
} as LoadContext;
|
||||
const presets = await loadPresets(context);
|
||||
expect(presets).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('esm form', async () => {
|
||||
const context = {
|
||||
siteConfigPath: __dirname,
|
||||
siteConfig: {
|
||||
presets: [
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.esm.js'),
|
||||
],
|
||||
},
|
||||
} as LoadContext;
|
||||
const presets = await loadPresets(context);
|
||||
expect(presets).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('ts form', async () => {
|
||||
const context = {
|
||||
siteConfigPath: __dirname,
|
||||
siteConfig: {
|
||||
presets: [
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.ts'),
|
||||
],
|
||||
},
|
||||
} as LoadContext;
|
||||
|
@ -44,7 +70,7 @@ describe('loadPresets', () => {
|
|||
siteConfigPath: __dirname,
|
||||
siteConfig: {
|
||||
presets: [
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.js'),
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.cjs.js'),
|
||||
path.join(__dirname, '__fixtures__/presets/preset-themes.js'),
|
||||
],
|
||||
},
|
||||
|
@ -58,7 +84,7 @@ describe('loadPresets', () => {
|
|||
siteConfigPath: __dirname,
|
||||
siteConfig: {
|
||||
presets: [
|
||||
[path.join(__dirname, '__fixtures__/presets/preset-plugins.js')],
|
||||
[path.join(__dirname, '__fixtures__/presets/preset-plugins.cjs.js')],
|
||||
],
|
||||
},
|
||||
} as unknown as LoadContext;
|
||||
|
@ -72,7 +98,7 @@ describe('loadPresets', () => {
|
|||
siteConfig: {
|
||||
presets: [
|
||||
[
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.js'),
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.cjs.js'),
|
||||
{docs: {path: '../'}},
|
||||
],
|
||||
],
|
||||
|
@ -88,7 +114,7 @@ describe('loadPresets', () => {
|
|||
siteConfig: {
|
||||
presets: [
|
||||
[
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.js'),
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.cjs.js'),
|
||||
{docs: {path: '../'}},
|
||||
],
|
||||
[
|
||||
|
@ -108,7 +134,7 @@ describe('loadPresets', () => {
|
|||
siteConfig: {
|
||||
presets: [
|
||||
[
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.js'),
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.cjs.js'),
|
||||
{docs: {path: '../'}},
|
||||
],
|
||||
path.join(__dirname, '__fixtures__/presets/preset-themes.js'),
|
||||
|
@ -125,7 +151,7 @@ describe('loadPresets', () => {
|
|||
siteConfig: {
|
||||
presets: [
|
||||
[
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.js'),
|
||||
path.join(__dirname, '__fixtures__/presets/preset-plugins.cjs.js'),
|
||||
{docs: {path: '../'}},
|
||||
],
|
||||
false,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import {createRequire} from 'module';
|
||||
import importFresh from 'import-fresh';
|
||||
import {loadFreshModule} from '@docusaurus/utils';
|
||||
import {loadPresets} from './presets';
|
||||
import {resolveModuleName} from './moduleShorthand';
|
||||
import type {
|
||||
|
@ -61,7 +61,9 @@ async function normalizePluginConfig(
|
|||
if (typeof pluginConfig === 'string') {
|
||||
const pluginModuleImport = pluginConfig;
|
||||
const pluginPath = pluginRequire.resolve(pluginModuleImport);
|
||||
const pluginModule = importFresh<ImportedPluginModule>(pluginPath);
|
||||
const pluginModule = (await loadFreshModule(
|
||||
pluginPath,
|
||||
)) as ImportedPluginModule;
|
||||
return {
|
||||
plugin: pluginModule.default ?? pluginModule,
|
||||
options: {},
|
||||
|
@ -88,7 +90,9 @@ async function normalizePluginConfig(
|
|||
if (typeof pluginConfig[0] === 'string') {
|
||||
const pluginModuleImport = pluginConfig[0];
|
||||
const pluginPath = pluginRequire.resolve(pluginModuleImport);
|
||||
const pluginModule = importFresh<ImportedPluginModule>(pluginPath);
|
||||
const pluginModule = (await loadFreshModule(
|
||||
pluginPath,
|
||||
)) as ImportedPluginModule;
|
||||
return {
|
||||
plugin: pluginModule.default ?? pluginModule,
|
||||
options: pluginConfig[1],
|
||||
|
|
|
@ -6,12 +6,13 @@
|
|||
*/
|
||||
|
||||
import {createRequire} from 'module';
|
||||
import importFresh from 'import-fresh';
|
||||
import {loadFreshModule} from '@docusaurus/utils';
|
||||
import {resolveModuleName} from './moduleShorthand';
|
||||
import type {
|
||||
LoadContext,
|
||||
PluginConfig,
|
||||
PresetConfigDefined,
|
||||
PresetModule,
|
||||
Preset,
|
||||
DocusaurusConfig,
|
||||
} from '@docusaurus/types';
|
||||
|
||||
|
@ -28,16 +29,13 @@ export async function loadPresets(
|
|||
// we are using `require.resolve` on those module names.
|
||||
const presetRequire = createRequire(context.siteConfigPath);
|
||||
|
||||
const {presets} = context.siteConfig;
|
||||
const plugins: PluginConfig[] = [];
|
||||
const themes: PluginConfig[] = [];
|
||||
const presets = context.siteConfig.presets.filter(
|
||||
(p): p is PresetConfigDefined => !!p,
|
||||
);
|
||||
|
||||
presets.forEach((presetItem) => {
|
||||
async function loadPreset(presetItem: PresetConfigDefined): Promise<Preset> {
|
||||
let presetModuleImport: string;
|
||||
let presetOptions = {};
|
||||
if (!presetItem) {
|
||||
return;
|
||||
}
|
||||
if (typeof presetItem === 'string') {
|
||||
presetModuleImport = presetItem;
|
||||
} else {
|
||||
|
@ -49,21 +47,20 @@ export async function loadPresets(
|
|||
'preset',
|
||||
);
|
||||
|
||||
const presetModule = importFresh<ImportedPresetModule>(
|
||||
presetRequire.resolve(presetName),
|
||||
);
|
||||
const preset = (presetModule.default ?? presetModule)(
|
||||
context,
|
||||
presetOptions,
|
||||
);
|
||||
const presetPath = presetRequire.resolve(presetName);
|
||||
const presetModule = (await loadFreshModule(
|
||||
presetPath,
|
||||
)) as ImportedPresetModule;
|
||||
|
||||
if (preset.plugins) {
|
||||
plugins.push(...preset.plugins);
|
||||
const presetFunction = presetModule.default ?? presetModule;
|
||||
|
||||
return presetFunction(context, presetOptions);
|
||||
}
|
||||
if (preset.themes) {
|
||||
themes.push(...preset.themes);
|
||||
}
|
||||
});
|
||||
|
||||
const loadedPresets = await Promise.all(presets.map(loadPreset));
|
||||
|
||||
const plugins = loadedPresets.flatMap((preset) => preset.plugins ?? []);
|
||||
const themes = loadedPresets.flatMap((preset) => preset.themes ?? []);
|
||||
|
||||
return {plugins, themes};
|
||||
}
|
||||
|
|
|
@ -60,7 +60,6 @@ cssnano
|
|||
csvg
|
||||
customizability
|
||||
dabit
|
||||
dabit
|
||||
daishi
|
||||
datagit
|
||||
datas
|
||||
|
@ -98,20 +97,22 @@ eslintcache
|
|||
estree
|
||||
evaluable
|
||||
execa
|
||||
execa
|
||||
externalwaiting
|
||||
failfast
|
||||
Fargate
|
||||
fbid
|
||||
février
|
||||
fienny
|
||||
flac
|
||||
flightcontrol
|
||||
formik
|
||||
fouc
|
||||
froms
|
||||
funboxteam
|
||||
gantt
|
||||
gabrielcsapo
|
||||
gantt
|
||||
getopts
|
||||
gifs
|
||||
gitgraph
|
||||
gitpod
|
||||
globbing
|
||||
|
@ -123,6 +124,7 @@ gtag
|
|||
hahaha
|
||||
hamel
|
||||
hardcoding
|
||||
hastscript
|
||||
hasura
|
||||
heavener
|
||||
héctor
|
||||
|
@ -136,6 +138,7 @@ hoverable
|
|||
husain
|
||||
ianad
|
||||
idempotency
|
||||
Iframes
|
||||
immer
|
||||
infima
|
||||
inlines
|
||||
|
@ -148,6 +151,7 @@ jakepartusch
|
|||
jamstack
|
||||
janvier
|
||||
javadoc
|
||||
jiti
|
||||
jmarcey
|
||||
jodyheavener
|
||||
joshcena
|
||||
|
@ -183,6 +187,7 @@ mathjax
|
|||
maxlynch
|
||||
maxresdefault
|
||||
mdast
|
||||
mdwn
|
||||
mdxa
|
||||
mdxast
|
||||
mdxhast
|
||||
|
@ -198,9 +203,8 @@ minifier
|
|||
mkcert
|
||||
mkdir
|
||||
mkdirs
|
||||
mkdocs
|
||||
mkdn
|
||||
mdwn
|
||||
mkdocs
|
||||
mkdown
|
||||
moesif
|
||||
msapplication
|
||||
|
@ -273,6 +277,7 @@ prerendered
|
|||
prerendering
|
||||
println
|
||||
prismjs
|
||||
producthunt
|
||||
profilo
|
||||
protobuf
|
||||
protobuffet
|
||||
|
@ -319,7 +324,6 @@ serializers
|
|||
setaf
|
||||
setext
|
||||
shiki
|
||||
shiki
|
||||
showinfo
|
||||
sida
|
||||
simen
|
||||
|
@ -328,7 +332,6 @@ sluggified
|
|||
sluggifies
|
||||
sluggify
|
||||
solana
|
||||
solana
|
||||
spâce
|
||||
stackblitz
|
||||
stackblitzrc
|
||||
|
@ -373,6 +376,7 @@ typecheck
|
|||
typechecks
|
||||
typedoc
|
||||
typesense
|
||||
unavatar
|
||||
unflat
|
||||
unist
|
||||
unlinkable
|
||||
|
@ -415,11 +419,3 @@ yangshunz
|
|||
zhou
|
||||
zoomable
|
||||
zpao
|
||||
hastscript
|
||||
Flightcontrol
|
||||
Fargate
|
||||
Flightcontrol's
|
||||
producthunt
|
||||
Gifs
|
||||
Iframes
|
||||
Unavatar
|
||||
|
|
|
@ -5,24 +5,24 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @type {import('@docusaurus/types').PluginConfig[]} */
|
||||
const dogfoodingThemeInstances = [
|
||||
/** @type {import('@docusaurus/types').PluginModule} */
|
||||
function swizzleThemeTests() {
|
||||
import type {PluginConfig, Plugin} from '@docusaurus/types';
|
||||
import type {Options as DocsOptions} from '@docusaurus/plugin-content-docs';
|
||||
import type {Options as BlogOptions} from '@docusaurus/plugin-content-blog';
|
||||
import type {Options as PageOptions} from '@docusaurus/plugin-content-pages';
|
||||
|
||||
export const dogfoodingThemeInstances: PluginConfig[] = [
|
||||
function swizzleThemeTests(): Plugin {
|
||||
return {
|
||||
name: 'swizzle-theme-tests',
|
||||
getThemePath: () => './_swizzle_theme_tests/src/theme',
|
||||
};
|
||||
},
|
||||
];
|
||||
exports.dogfoodingThemeInstances = dogfoodingThemeInstances;
|
||||
|
||||
/** @type {import('@docusaurus/types').PluginConfig[]} */
|
||||
const dogfoodingPluginInstances = [
|
||||
export const dogfoodingPluginInstances: PluginConfig[] = [
|
||||
[
|
||||
'content-docs', // Shorthand
|
||||
/** @type {import('@docusaurus/plugin-content-docs').Options} */
|
||||
({
|
||||
{
|
||||
id: 'docs-tests',
|
||||
routeBasePath: '/tests/docs',
|
||||
sidebarPath: '_dogfooding/docs-tests-sidebars.js',
|
||||
|
@ -43,20 +43,20 @@ const dogfoodingPluginInstances = [
|
|||
const eligibleDocIndexNames = [
|
||||
'index',
|
||||
'readme',
|
||||
directories[0].toLowerCase(),
|
||||
directories[0]!.toLowerCase(),
|
||||
'intro',
|
||||
];
|
||||
return eligibleDocIndexNames.includes(fileName.toLowerCase());
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
} satisfies DocsOptions,
|
||||
],
|
||||
|
||||
[
|
||||
'@docusaurus/plugin-content-blog', // Longhand
|
||||
/** @type {import('@docusaurus/plugin-content-blog').Options} */
|
||||
({
|
||||
{
|
||||
id: 'blog-tests',
|
||||
path: '_dogfooding/_blog tests',
|
||||
routeBasePath: '/tests/blog',
|
||||
|
@ -72,21 +72,19 @@ const dogfoodingPluginInstances = [
|
|||
frontMatter.hide_reading_time
|
||||
? undefined
|
||||
: defaultReadingTime({content, options: {wordsPerMinute: 5}}),
|
||||
}),
|
||||
} satisfies BlogOptions,
|
||||
],
|
||||
|
||||
[
|
||||
require.resolve('@docusaurus/plugin-content-pages'), // Full path
|
||||
/** @type {import('@docusaurus/plugin-content-pages').Options} */
|
||||
({
|
||||
{
|
||||
id: 'pages-tests',
|
||||
path: '_dogfooding/_pages tests',
|
||||
routeBasePath: '/tests/pages',
|
||||
}),
|
||||
} satisfies PageOptions,
|
||||
],
|
||||
|
||||
/** @type {import('@docusaurus/types').Plugin} */
|
||||
function clientModuleTestPlugin() {
|
||||
function clientModuleTestPlugin(): Plugin {
|
||||
return {
|
||||
name: 'client-module-test-plugin',
|
||||
getClientModules() {
|
||||
|
@ -99,9 +97,7 @@ const dogfoodingPluginInstances = [
|
|||
},
|
||||
];
|
||||
|
||||
exports.dogfoodingPluginInstances = dogfoodingPluginInstances;
|
||||
|
||||
exports.dogfoodingRedirects = [
|
||||
export const dogfoodingRedirects: {from: string[]; to: string}[] = [
|
||||
{
|
||||
from: ['/home/'],
|
||||
to: '/',
|
|
@ -362,13 +362,22 @@ console.log('hello');
|
|||
|
||||
All the official packages (Unified, Remark, Rehype...) in the MDX ecosystem are now [**ES Modules only**](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) and do not support [CommonJS](https://nodejs.org/api/modules.html#modules-commonjs-modules) anymore.
|
||||
|
||||
In practice this means that you can't do `require("remark-plugin")` anymore. Unfortunately the Docusaurus config file only supports CommonJS at the moment, and you can't use `import MyRemarkPlugin from "remark-plugin"`.
|
||||
In practice this means that you can't do `require("remark-plugin")` anymore.
|
||||
|
||||
:::tip How to prepare
|
||||
|
||||
Using dynamic imports is a good workaround that enables you to import ES modules inside a CommonJS module. Fortunately, the [Docusaurus config supports the usage of an async function](/docs/configuration#syntax-to-declare-docusaurus-config) to let you do so.
|
||||
Docusaurus v3 now supports [**ES Modules**](https://flaviocopes.com/es-modules/) configuration files. We recommend that you migrate your config file to ES module, that enables you to import the Remark plugins easily:
|
||||
|
||||
You can start refactoring your config to use **async dynamic imports** today. Refer to the [MDX plugin installation documentation](/docs/3.0.0-beta.0/markdown-features/plugins#installing-plugins) for details.
|
||||
```js title="docusaurus.config.js"
|
||||
import remarkPlugin from 'remark-plugin';
|
||||
|
||||
export default {
|
||||
title: 'Docusaurus',
|
||||
/* site config using remark plugins here */
|
||||
};
|
||||
```
|
||||
|
||||
If you want to keep using CommonJS modules, you can use dynamic imports as a workaround that enables you to import ES modules inside a CommonJS module. Fortunately, the [Docusaurus config supports the usage of an async function](/docs/configuration#syntax-to-declare-docusaurus-config) to let you do so.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = async function () {
|
||||
|
|
|
@ -20,7 +20,7 @@ This diagram shows how Docusaurus works to build your app. Plugins each collect
|
|||
|
||||
Although you (either plugin authors or site creators) are writing JavaScript all the time, bear in mind that the JS is actually run in different environments:
|
||||
|
||||
- All plugin lifecycle methods are run in Node. Therefore, until we support ES Modules in our codebase, plugin source code must be provided as CommonJS that can be `require`'d.
|
||||
- All plugin lifecycle methods are run in Node. Therefore, until we support ES Modules in our codebase, plugin source code must be provided as ES modules that can be imported, or CommonJS that can be `require`'d.
|
||||
- The theme code is built with Webpack. They can be provided as ESM—following React conventions.
|
||||
|
||||
Plugin code and theme code never directly import each other: they only communicate through protocols (in our case, through JSON temp files and calls to `addRoute`). A useful mental model is to imagine that the plugins are not written in JavaScript, but in another language like Rust. The only way to interact with plugins for the user is through `docusaurus.config.js`, which itself is run in Node (hence you can use `require` and pass callbacks as plugin options).
|
||||
|
|
|
@ -11,7 +11,7 @@ A plugin is a function that takes two parameters: `context` and `options`. It re
|
|||
You can use a plugin as a function directly included in the Docusaurus config file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
// highlight-start
|
||||
|
@ -38,7 +38,7 @@ module.exports = {
|
|||
You can use a plugin as a module path referencing a separate file or npm package:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
// without options:
|
||||
|
@ -52,7 +52,7 @@ module.exports = {
|
|||
Then in the folder `my-plugin`, you can create an `index.js` such as this:
|
||||
|
||||
```js title="my-plugin/index.js"
|
||||
module.exports = async function myPlugin(context, options) {
|
||||
export default async function myPlugin(context, options) {
|
||||
// ...
|
||||
return {
|
||||
name: 'my-plugin',
|
||||
|
@ -64,7 +64,7 @@ module.exports = async function myPlugin(context, options) {
|
|||
},
|
||||
/* other lifecycle API */
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
@ -99,7 +99,7 @@ This is a contrived example: in practice, `@docusaurus/theme-classic` provides t
|
|||
:::
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// highlight-next-line
|
||||
themes: ['theme-blog'],
|
||||
plugins: ['plugin-content-blog'],
|
||||
|
@ -109,7 +109,7 @@ module.exports = {
|
|||
And if you want to use Bootstrap styling, you can swap out the theme with `theme-blog-bootstrap` (another fictitious non-existing theme):
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// highlight-next-line
|
||||
themes: ['theme-blog-bootstrap'],
|
||||
plugins: ['plugin-content-blog'],
|
||||
|
|
|
@ -18,12 +18,20 @@ Refer to the Getting Started [**Configuration**](../configuration.mdx) for examp
|
|||
|
||||
`docusaurus.config.js` contains configurations for your site and is placed in the root directory of your site.
|
||||
|
||||
This file is run in Node.js using the [**CommonJS**](https://flaviocopes.com/commonjs/) module system, and should export a site configuration object, or a function that creates it.
|
||||
This file is run in Node.js and should export a site configuration object, or a function that creates it.
|
||||
|
||||
The `docusaurus.config.js` file supports:
|
||||
|
||||
- [**ES Modules**](https://flaviocopes.com/es-modules/)
|
||||
- [**CommonJS**](https://flaviocopes.com/commonjs/)
|
||||
- [**TypeScript**](../typescript-support.mdx#typing-config)
|
||||
|
||||
hey
|
||||
|
||||
Examples:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
title: 'Docusaurus',
|
||||
url: 'https://docusaurus.io',
|
||||
// your site config ...
|
||||
|
@ -31,13 +39,13 @@ module.exports = {
|
|||
```
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = async function createConfigAsync() {
|
||||
export default async function createConfigAsync() {
|
||||
return {
|
||||
title: 'Docusaurus',
|
||||
url: 'https://docusaurus.io',
|
||||
// your site config ...
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
:::tip
|
||||
|
@ -55,7 +63,7 @@ Refer to [**Syntax to declare `docusaurus.config.js`**](../configuration.mdx#syn
|
|||
Title for your website. Will be used in metadata and as browser tab title.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
title: 'Docusaurus',
|
||||
};
|
||||
```
|
||||
|
@ -67,7 +75,7 @@ module.exports = {
|
|||
URL for your website. This can also be considered the top-level hostname. For example, `https://facebook.github.io` is the URL of https://facebook.github.io/metro/, and `https://docusaurus.io` is the URL for https://docusaurus.io. This field is related to the [`baseUrl`](#baseUrl) field.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
url: 'https://docusaurus.io',
|
||||
};
|
||||
```
|
||||
|
@ -79,7 +87,7 @@ module.exports = {
|
|||
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 = {
|
||||
export default {
|
||||
baseUrl: '/',
|
||||
};
|
||||
```
|
||||
|
@ -93,7 +101,7 @@ module.exports = {
|
|||
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 = {
|
||||
export default {
|
||||
favicon: '/img/favicon.ico',
|
||||
};
|
||||
```
|
||||
|
@ -127,7 +135,7 @@ Example:
|
|||
{/* cSpell:ignore فارسی */}
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'fa'],
|
||||
|
@ -171,7 +179,7 @@ This option adds `<meta name="robots" content="noindex, nofollow">` to every pag
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
noIndex: true, // Defaults to `false`
|
||||
};
|
||||
```
|
||||
|
@ -213,7 +221,7 @@ By default, it displays a warning after you run `yarn start` or `yarn build`.
|
|||
The tagline for your website.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
tagline:
|
||||
'Docusaurus makes it easy to maintain Open Source documentation websites.',
|
||||
};
|
||||
|
@ -226,7 +234,7 @@ module.exports = {
|
|||
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 = {
|
||||
export default {
|
||||
// Docusaurus' organization is facebook
|
||||
organizationName: 'facebook',
|
||||
};
|
||||
|
@ -239,7 +247,7 @@ module.exports = {
|
|||
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 = {
|
||||
export default {
|
||||
projectName: 'docusaurus',
|
||||
};
|
||||
```
|
||||
|
@ -251,7 +259,7 @@ module.exports = {
|
|||
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 = {
|
||||
export default {
|
||||
deploymentBranch: 'gh-pages',
|
||||
};
|
||||
```
|
||||
|
@ -263,7 +271,7 @@ module.exports = {
|
|||
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 = {
|
||||
export default {
|
||||
githubHost: 'github.com',
|
||||
};
|
||||
```
|
||||
|
@ -275,7 +283,7 @@ module.exports = {
|
|||
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 = {
|
||||
export default {
|
||||
githubPort: '22',
|
||||
};
|
||||
```
|
||||
|
@ -289,7 +297,7 @@ The [theme configuration](./themes/theme-configuration.mdx) object to customize
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
docs: {
|
||||
sidebar: {
|
||||
|
@ -358,7 +366,7 @@ type PluginConfig = string | [string, any] | PluginModule | [PluginModule, any];
|
|||
See [plugin method references](./plugin-methods/README.mdx) for the shape of a `PluginModule`.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
'docusaurus-plugin-awesome',
|
||||
['docusuarus-plugin-confetti', {fancy: false}],
|
||||
|
@ -376,7 +384,7 @@ module.exports = {
|
|||
- Type: `PluginConfig[]`
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themes: ['@docusaurus/theme-classic'],
|
||||
};
|
||||
```
|
||||
|
@ -390,7 +398,7 @@ type PresetConfig = string | [string, any];
|
|||
```
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [],
|
||||
};
|
||||
```
|
||||
|
@ -426,7 +434,7 @@ type MarkdownConfig = {
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
markdown: {
|
||||
format: 'mdx',
|
||||
mermaid: true,
|
||||
|
@ -464,7 +472,7 @@ Docusaurus guards `docusaurus.config.js` from unknown fields. To add a custom fi
|
|||
- Type: `Object`
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
customFields: {
|
||||
admin: 'endi',
|
||||
superman: 'lol',
|
||||
|
@ -487,7 +495,7 @@ An array of paths, relative to the site's directory or absolute. Files under the
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
staticDirectories: ['static'],
|
||||
};
|
||||
```
|
||||
|
@ -501,7 +509,7 @@ An array of tags that will be inserted in the HTML `<head>`. The values must be
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
headTags: [
|
||||
{
|
||||
tagName: 'link',
|
||||
|
@ -527,7 +535,7 @@ Note that `<script>` added here are render-blocking, so you might want to add `a
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
scripts: [
|
||||
// String format.
|
||||
'https://docusaurus.io/script.js',
|
||||
|
@ -549,7 +557,7 @@ An array of CSS sources to load. The values can be either strings or plain objec
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
stylesheets: [
|
||||
// String format.
|
||||
'https://docusaurus.io/style.css',
|
||||
|
@ -574,11 +582,8 @@ An array of [client modules](../advanced/client.mdx#client-modules) to load glob
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
clientModules: [
|
||||
require.resolve('./mySiteGlobalJs.js'),
|
||||
require.resolve('./mySiteGlobalCss.css'),
|
||||
],
|
||||
export default {
|
||||
clientModules: ['./mySiteGlobalJs.js', './mySiteGlobalCss.css'],
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -591,7 +596,7 @@ An HTML template written in [Eta's syntax](https://eta.js.org/docs/syntax#syntax
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
ssrTemplate: `<!DOCTYPE html>
|
||||
<html <%~ it.htmlAttributes %>>
|
||||
<head>
|
||||
|
@ -631,7 +636,7 @@ Will be used as title delimiter in the generated `<title>` tag.
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
titleDelimiter: '🦖', // Defaults to `|`
|
||||
};
|
||||
```
|
||||
|
@ -645,7 +650,7 @@ When enabled, will show a banner in case your site can't load its CSS or JavaScr
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
baseUrlIssueBanner: true, // Defaults to `true`
|
||||
};
|
||||
```
|
||||
|
|
|
@ -47,7 +47,7 @@ Here's a mental model for a presumptuous plugin implementation.
|
|||
// A JavaScript function that returns an object.
|
||||
// `context` is provided by Docusaurus. Example: siteConfig can be accessed from context.
|
||||
// `opts` is the user-defined options.
|
||||
async function myPlugin(context, opts) {
|
||||
export default async function myPlugin(context, opts) {
|
||||
return {
|
||||
// A compulsory field used as the namespace for directories to cache
|
||||
// the intermediate data for each plugin.
|
||||
|
@ -132,15 +132,13 @@ async function myPlugin(context, opts) {
|
|||
};
|
||||
}
|
||||
|
||||
myPlugin.validateOptions = ({options, validate}) => {
|
||||
export function validateOptions({options, validate}) {
|
||||
const validatedOptions = validate(myValidationSchema, options);
|
||||
return validatedOptions;
|
||||
};
|
||||
}
|
||||
|
||||
myPlugin.validateThemeConfig = ({themeConfig, validate}) => {
|
||||
export function validateThemeConfig({themeConfig, validate}) {
|
||||
const validatedThemeConfig = validate(myValidationSchema, options);
|
||||
return validatedThemeConfig;
|
||||
};
|
||||
|
||||
module.exports = myPlugin;
|
||||
}
|
||||
```
|
||||
|
|
|
@ -15,8 +15,9 @@ Use this for files that are consumed server-side, because theme files are automa
|
|||
Example:
|
||||
|
||||
```js title="docusaurus-plugin/src/index.js"
|
||||
const path = require('path');
|
||||
module.exports = function (context, options) {
|
||||
import path from 'path';
|
||||
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
// highlight-start
|
||||
|
@ -26,7 +27,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `extendCli(cli)` {#extendCli}
|
||||
|
@ -42,7 +43,7 @@ The commander version matters! We use commander v5, and make sure you are referr
|
|||
Example:
|
||||
|
||||
```js title="docusaurus-plugin/src/index.js"
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
// highlight-start
|
||||
|
@ -56,7 +57,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `getThemePath()` {#getThemePath}
|
||||
|
@ -66,9 +67,7 @@ Returns the path to the directory where the theme components can be found. When
|
|||
For example, your `getThemePath` can be:
|
||||
|
||||
```js title="my-theme/src/index.js"
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'my-theme',
|
||||
// highlight-start
|
||||
|
@ -77,7 +76,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `getTypeScriptThemePath()` {#getTypeScriptThemePath}
|
||||
|
@ -95,9 +94,7 @@ You should also format these files with Prettier. Remember—JS files can and wi
|
|||
Example:
|
||||
|
||||
```js title="my-theme/src/index.js"
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'my-theme',
|
||||
// highlight-start
|
||||
|
@ -111,7 +108,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `getSwizzleComponentList()` {#getSwizzleComponentList}
|
||||
|
@ -121,7 +118,8 @@ module.exports = function (context, options) {
|
|||
Returns a list of stable components that are considered safe for swizzling. These components will be swizzlable without `--danger`. All components are considered unstable by default. If an empty array is returned, all components are considered unstable. If `undefined` is returned, all components are considered stable.
|
||||
|
||||
```js title="my-theme/src/index.js"
|
||||
const swizzleAllowedComponents = [
|
||||
export function getSwizzleComponentList() {
|
||||
return [
|
||||
'CodeBlock',
|
||||
'DocSidebar',
|
||||
'Footer',
|
||||
|
@ -130,6 +128,5 @@ const swizzleAllowedComponents = [
|
|||
'hooks/useTheme',
|
||||
'prism-include-languages',
|
||||
];
|
||||
|
||||
myTheme.getSwizzleComponentList = () => swizzleAllowedComponents;
|
||||
}
|
||||
```
|
||||
|
|
|
@ -19,8 +19,8 @@ These files will be written by the [`write-translations` CLI](../../cli.mdx#docu
|
|||
|
||||
Example:
|
||||
|
||||
```js
|
||||
module.exports = function (context, options) {
|
||||
```js title="my-plugin.js"
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'my-plugin',
|
||||
// highlight-start
|
||||
|
@ -40,7 +40,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `translateContent({content,translationFiles})` {#translateContent}
|
||||
|
@ -53,8 +53,8 @@ The `contentLoaded()` lifecycle will be called with the localized plugin content
|
|||
|
||||
Example:
|
||||
|
||||
```js
|
||||
module.exports = function (context, options) {
|
||||
```js title="my-plugin.js"
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'my-plugin',
|
||||
// highlight-start
|
||||
|
@ -69,7 +69,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `translateThemeConfig({themeConfig,translationFiles})` {#translateThemeConfig}
|
||||
|
@ -80,8 +80,8 @@ Returns the localized `themeConfig`.
|
|||
|
||||
Example:
|
||||
|
||||
```js
|
||||
module.exports = function (context, options) {
|
||||
```js title="my-plugin.js"
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'my-theme',
|
||||
// highlight-start
|
||||
|
@ -96,7 +96,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `async getDefaultCodeTranslationMessages()` {#getDefaultCodeTranslationMessages}
|
||||
|
@ -107,8 +107,8 @@ It should return messages in `Record<string, string>`, where keys are translatio
|
|||
|
||||
Example:
|
||||
|
||||
```js
|
||||
module.exports = function (context, options) {
|
||||
```js title="my-plugin.js"
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'my-theme',
|
||||
// highlight-start
|
||||
|
@ -117,5 +117,5 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -14,7 +14,7 @@ Plugins should use this lifecycle to fetch from data sources (filesystem, remote
|
|||
For example, this plugin below returns a random integer between 1 and 10 as content.
|
||||
|
||||
```js title="docusaurus-plugin/src/index.js"
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
// highlight-start
|
||||
|
@ -23,7 +23,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `async contentLoaded({content, actions})` {#contentLoaded}
|
||||
|
@ -183,7 +183,7 @@ You may use them to return your webpack configuration conditionally.
|
|||
For example, this plugin below modify the webpack config to transpile `.foo` files.
|
||||
|
||||
```js title="docusaurus-plugin/src/index.js"
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'custom-docusaurus-plugin',
|
||||
// highlight-start
|
||||
|
@ -202,7 +202,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### `content` {#content-1}
|
||||
|
@ -216,7 +216,7 @@ We merge the Webpack configuration parts of plugins into the global Webpack conf
|
|||
It is possible to specify the merge strategy. For example, if you want a webpack rule to be prepended instead of appended:
|
||||
|
||||
```js title="docusaurus-plugin/src/index.js"
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'custom-docusaurus-plugin',
|
||||
configureWebpack(config, isServer, utils) {
|
||||
|
@ -228,7 +228,7 @@ module.exports = function (context, options) {
|
|||
};
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Read the [webpack-merge strategy doc](https://github.com/survivejs/webpack-merge#merging-with-strategies) for more details.
|
||||
|
@ -238,7 +238,7 @@ Read the [webpack-merge strategy doc](https://github.com/survivejs/webpack-merge
|
|||
The dev server can be configured through returning a `devServer` field.
|
||||
|
||||
```js title="docusaurus-plugin/src/index.js"
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'custom-docusaurus-plugin',
|
||||
configureWebpack(config, isServer, utils) {
|
||||
|
@ -251,7 +251,7 @@ module.exports = function (context, options) {
|
|||
};
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `configurePostCss(options)` {#configurePostCss}
|
||||
|
@ -272,7 +272,7 @@ const postcssOptions = {
|
|||
Example:
|
||||
|
||||
```js title="docusaurus-plugin/src/index.js"
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
// highlight-start
|
||||
|
@ -283,7 +283,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `postBuild(props)` {#postBuild}
|
||||
|
@ -309,7 +309,7 @@ interface Props {
|
|||
Example:
|
||||
|
||||
```js title="docusaurus-plugin/src/index.js"
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
// highlight-start
|
||||
|
@ -321,7 +321,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `injectHtmlTags({content})` {#injectHtmlTags}
|
||||
|
@ -361,7 +361,7 @@ type HtmlTagObject = {
|
|||
Example:
|
||||
|
||||
```js title="docusaurus-plugin/src/index.js"
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
loadContent: async () => {
|
||||
|
@ -394,7 +394,7 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Tags will be added as follows:
|
||||
|
@ -410,9 +410,7 @@ Returns an array of paths to the [client modules](../../advanced/client.mdx#clie
|
|||
As an example, to make your theme load a `customCss` or `customJs` file path from `options` passed in by the user:
|
||||
|
||||
```js title="my-theme/src/index.js"
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function (context, options) {
|
||||
export default function (context, options) {
|
||||
const {customCss, customJs} = options || {};
|
||||
return {
|
||||
name: 'name-of-my-theme',
|
||||
|
@ -422,5 +420,5 @@ module.exports = function (context, options) {
|
|||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -22,34 +22,14 @@ Returns validated and normalized options for the plugin. This method is called b
|
|||
|
||||
[Joi](https://www.npmjs.com/package/joi) is recommended for validation and normalization of options.
|
||||
|
||||
To avoid mixing Joi versions, use `const {Joi} = require("@docusaurus/utils-validation")`
|
||||
To avoid mixing Joi versions, use `import {Joi} from '@docusaurus/utils-validation'`
|
||||
|
||||
:::
|
||||
|
||||
If you don't use **[Joi](https://www.npmjs.com/package/joi)** for validation you can throw an Error in case of invalid options and return options in case of success.
|
||||
|
||||
```js title="my-plugin/src/index.js"
|
||||
function myPlugin(context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
// rest of methods
|
||||
};
|
||||
}
|
||||
|
||||
// highlight-start
|
||||
myPlugin.validateOptions = ({options, validate}) => {
|
||||
const validatedOptions = validate(myValidationSchema, options);
|
||||
return validatedOptions;
|
||||
};
|
||||
// highlight-end
|
||||
|
||||
module.exports = myPlugin;
|
||||
```
|
||||
|
||||
In TypeScript, you can also choose to export this as a separate named export.
|
||||
|
||||
```ts title="my-plugin/src/index.ts"
|
||||
export default function (context, options) {
|
||||
export default function myPlugin(context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
// rest of methods
|
||||
|
@ -80,34 +60,14 @@ Return validated and normalized configuration for the theme.
|
|||
|
||||
[Joi](https://www.npmjs.com/package/joi) is recommended for validation and normalization of theme config.
|
||||
|
||||
To avoid mixing Joi versions, use `const {Joi} = require("@docusaurus/utils-validation")`
|
||||
To avoid mixing Joi versions, use `import {Joi} from '@docusaurus/utils-validation'`
|
||||
|
||||
:::
|
||||
|
||||
If you don't use **[Joi](https://www.npmjs.com/package/joi)** for validation you can throw an Error in case of invalid options.
|
||||
|
||||
```js title="my-theme/src/index.js"
|
||||
function myPlugin(context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
// rest of methods
|
||||
};
|
||||
}
|
||||
|
||||
// highlight-start
|
||||
myPlugin.validateThemeConfig = ({themeConfig, validate}) => {
|
||||
const validatedThemeConfig = validate(myValidationSchema, options);
|
||||
return validatedThemeConfig;
|
||||
};
|
||||
// highlight-end
|
||||
|
||||
module.exports = validateThemeConfig;
|
||||
```
|
||||
|
||||
In TypeScript, you can also choose to export this as a separate named export.
|
||||
|
||||
```ts title="my-theme/src/index.ts"
|
||||
export default function (context, options) {
|
||||
export default function myPlugin(context, options) {
|
||||
return {
|
||||
name: 'docusaurus-plugin',
|
||||
// rest of methods
|
||||
|
|
|
@ -89,7 +89,7 @@ type CreateRedirectsFn = (path: string) => string[] | string | null | undefined;
|
|||
Here's an example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-client-redirects',
|
||||
|
|
|
@ -169,7 +169,7 @@ const config = {
|
|||
blogPostComponent: '@theme/BlogPostPage',
|
||||
blogTagsListComponent: '@theme/BlogTagsListPage',
|
||||
blogTagsPostsComponent: '@theme/BlogTagsPostsPage',
|
||||
remarkPlugins: [require('remark-math')],
|
||||
remarkPlugins: [require('./my-remark-plugin')],
|
||||
rehypePlugins: [],
|
||||
beforeDefaultRemarkPlugins: [],
|
||||
beforeDefaultRehypePlugins: [],
|
||||
|
|
|
@ -234,7 +234,7 @@ const config = {
|
|||
},
|
||||
docLayoutComponent: '@theme/DocPage',
|
||||
docItemComponent: '@theme/DocItem',
|
||||
remarkPlugins: [require('remark-math')],
|
||||
remarkPlugins: [require('./my-remark-plugin')],
|
||||
rehypePlugins: [],
|
||||
beforeDefaultRemarkPlugins: [],
|
||||
beforeDefaultRehypePlugins: [],
|
||||
|
|
|
@ -72,7 +72,7 @@ const config = {
|
|||
'**/__tests__/**',
|
||||
],
|
||||
mdxPageComponent: '@theme/MDXPage',
|
||||
remarkPlugins: [require('remark-math')],
|
||||
remarkPlugins: [require('./my-remark-plugin')],
|
||||
rehypePlugins: [],
|
||||
beforeDefaultRemarkPlugins: [],
|
||||
beforeDefaultRehypePlugins: [],
|
||||
|
|
|
@ -21,7 +21,7 @@ If you use the plugin via the classic preset, the preset will **enable the plugi
|
|||
If you use a standalone plugin, you may need to achieve the same effect by checking the environment:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
// highlight-next-line
|
||||
process.env.NODE_ENV === 'production' && '@docusaurus/plugin-debug',
|
||||
|
@ -75,7 +75,7 @@ Most Docusaurus users configure this plugin through the preset options.
|
|||
If you use a preset, configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic):
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -96,7 +96,7 @@ module.exports = {
|
|||
If you are using a standalone plugin, provide options directly to the plugin:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// highlight-next-line
|
||||
plugins: ['@docusaurus/plugin-debug'],
|
||||
};
|
||||
|
|
|
@ -73,7 +73,7 @@ Accepted fields:
|
|||
Here's an example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-ideal-image',
|
||||
|
|
|
@ -20,7 +20,7 @@ Create a [PWA manifest](https://web.dev/add-manifest/) at `./static/manifest.jso
|
|||
Modify `docusaurus.config.js` with a minimal PWA config, like:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-pwa',
|
||||
|
@ -148,7 +148,7 @@ The [`standalone` strategy](https://petelepage.com/blog/2019/07/is-my-pwa-instal
|
|||
- Default: `{}`
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-pwa',
|
||||
|
@ -179,7 +179,7 @@ module.exports = {
|
|||
Array of objects containing `tagName` and key-value pairs for attributes to inject into the `<head>` tag. Technically you can inject any head tag through this, but it's ideally used for tags to make your site PWA compliant. Here's a list of tag to make your app fully compliant:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-pwa',
|
||||
|
@ -288,7 +288,7 @@ The Docusaurus site manifest can serve as an inspiration:
|
|||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
<CodeBlock className="language-json">
|
||||
{JSON.stringify(require("@site/static/manifest.json"),null,2)}
|
||||
{JSON.stringify(require('@site/static/manifest.json'),null,2)}
|
||||
</CodeBlock>
|
||||
```
|
||||
|
||||
|
|
|
@ -58,6 +58,6 @@ Most Docusaurus users configure this plugin through the preset options.
|
|||
// Plugin Options: @docusaurus/theme-classic
|
||||
|
||||
const config = {
|
||||
customCss: require.resolve('./src/css/custom.css'),
|
||||
customCss: './src/css/custom.css',
|
||||
};
|
||||
```
|
||||
|
|
|
@ -38,7 +38,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// highlight-start
|
||||
colorMode: {
|
||||
|
@ -80,7 +80,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// highlight-next-line
|
||||
image: 'img/docusaurus.png',
|
||||
|
@ -109,7 +109,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// highlight-next-line
|
||||
metadata: [{name: 'twitter:card', content: 'summary'}],
|
||||
|
@ -142,7 +142,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// highlight-start
|
||||
announcementBar: {
|
||||
|
@ -209,7 +209,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
title: 'Site Title',
|
||||
|
@ -236,7 +236,7 @@ module.exports = {
|
|||
You can add items to the navbar via `themeConfig.navbar.items`.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
// highlight-start
|
||||
|
@ -311,7 +311,7 @@ In addition to the fields above, you can specify other arbitrary attributes that
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
@ -368,7 +368,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
@ -422,7 +422,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
@ -471,7 +471,7 @@ Use this navbar item type if your sidebar is updated often and the order is not
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
@ -490,7 +490,7 @@ module.exports = {
|
|||
```
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
tutorial: [
|
||||
{
|
||||
type: 'autogenerated',
|
||||
|
@ -537,7 +537,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
@ -580,7 +580,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
@ -625,7 +625,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
@ -668,7 +668,7 @@ However, with this special navbar item type, you can change the default location
|
|||
```
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
@ -704,7 +704,7 @@ You can also render your own HTML markup inside a navbar item using this navbar
|
|||
```
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
@ -726,7 +726,7 @@ module.exports = {
|
|||
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.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
// highlight-next-line
|
||||
|
@ -743,7 +743,7 @@ You can set the static Navbar style without disabling the theme switching abilit
|
|||
Currently, there are two possible style options: `dark` and `primary` (based on the `--ifm-color-primary` color). You can see the styles preview in the [Infima documentation](https://infima.dev/docs/components/navbar/).
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
// highlight-next-line
|
||||
|
@ -799,14 +799,14 @@ By default, we use [Palenight](https://github.com/FormidableLabs/prism-react-ren
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
const {themes} = require('prism-react-renderer');
|
||||
import {themes as prismThemes} from 'prism-react-renderer';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
prism: {
|
||||
// highlight-start
|
||||
theme: themes.github,
|
||||
darkTheme: themes.dracula,
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.dracula,
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
|
@ -826,7 +826,7 @@ You can set a default language for code blocks if no language is added after the
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
prism: {
|
||||
// highlight-next-line
|
||||
|
@ -860,7 +860,7 @@ Accepted fields:
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// highlight-start
|
||||
footer: {
|
||||
|
@ -917,7 +917,7 @@ Accepted fields of each `FooterItem`:
|
|||
Example multi-column configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
footer: {
|
||||
// highlight-start
|
||||
links: [
|
||||
|
@ -969,7 +969,7 @@ A simple footer just has a list of `FooterItem`s displayed in a row.
|
|||
Example simple configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
footer: {
|
||||
// highlight-start
|
||||
links: [
|
||||
|
@ -1018,7 +1018,7 @@ You can adjust the default table of contents via `themeConfig.tableOfContents`.
|
|||
Example configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// highlight-start
|
||||
tableOfContents: {
|
||||
|
|
|
@ -14,7 +14,7 @@ npm install --save @docusaurus/theme-live-codeblock
|
|||
### Configuration {#configuration}
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: ['@docusaurus/theme-live-codeblock'],
|
||||
themeConfig: {
|
||||
liveCodeBlock: {
|
||||
|
|
|
@ -14,7 +14,7 @@ npm install --save @docusaurus/theme-mermaid
|
|||
## Configuration {#configuration}
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themes: ['@docusaurus/theme-mermaid'],
|
||||
// In order for Mermaid code blocks in Markdown to work,
|
||||
// you also need to enable the Remark plugin with this option
|
||||
|
|
|
@ -22,7 +22,7 @@ To set up your site's blog, start by creating a `blog` directory.
|
|||
Then, add an item link to your blog within `docusaurus.config.js`:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// ...
|
||||
navbar: {
|
||||
|
@ -108,7 +108,7 @@ But anything from here on down will not be.
|
|||
By default, 10 posts are shown on each blog list page, but you can control pagination with the `postsPerPage` option in the plugin configuration. If you set `postsPerPage: 'ALL'`, pagination will be disabled and all posts will be displayed on the first page. You can also add a meta description to the blog list page for better SEO:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
presets: [
|
||||
[
|
||||
|
@ -134,7 +134,7 @@ The blog sidebar displays recent blog posts. The default number of items shown i
|
|||
You can also alter the sidebar heading text with the `blogSidebarTitle` option. For example, if you have set `blogSidebarCount: 'ALL'`, instead of the default "Recent posts", you may rather make it say "All posts":
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -385,7 +385,7 @@ An author, either declared through front matter or through the authors map, need
|
|||
Docusaurus generates a reading time estimation for each blog post based on word count. We provide an option to customize this.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -419,7 +419,7 @@ Use the callback for all your customization needs:
|
|||
**Disable reading time on one page:**
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -457,7 +457,7 @@ This page will no longer display the reading time stats!
|
|||
**Pass options to the default reading time function:**
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -482,9 +482,9 @@ module.exports = {
|
|||
**Use a custom implementation of reading time:**
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
const myReadingTime = require('./myReadingTime');
|
||||
import myReadingTime from './myReadingTime';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -539,7 +539,7 @@ type BlogOptions = {
|
|||
Example usage:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
presets: [
|
||||
[
|
||||
|
@ -600,7 +600,7 @@ https://example.com/blog/feed.json
|
|||
You can run your Docusaurus 2 site without a dedicated landing page and instead have your blog's post list page as the index page. Set the `routeBasePath` to be `'/'` to serve the blog through the root route `example.com/` instead of the subroute `example.com/blog/`.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
presets: [
|
||||
[
|
||||
|
@ -640,7 +640,7 @@ Set the `routeBasePath` to the URL route that you want your second blog to be ac
|
|||
As documented for [multi-instance plugins](./using-plugins.mdx#multi-instance-plugins-and-plugin-ids), you need to assign a unique ID to the plugins.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
[
|
||||
|
|
|
@ -25,15 +25,28 @@ The `docusaurus.config.js` file is run in Node.js and should export either:
|
|||
|
||||
:::info
|
||||
|
||||
The `docusaurus.config.js` file only supports the [**CommonJS**](https://flaviocopes.com/commonjs/) module system:
|
||||
The `docusaurus.config.js` file supports:
|
||||
|
||||
- **Required:** use `module.exports = /* your config*/` to export your Docusaurus config
|
||||
- **Optional:** use `require("lib")` to import Node.js packages
|
||||
- **Optional:** use `await import("lib")` (dynamic import) in an async function to import ESM-Only Node.js packages
|
||||
- [**ES Modules**](https://flaviocopes.com/es-modules/)
|
||||
- [**CommonJS**](https://flaviocopes.com/commonjs/)
|
||||
- [**TypeScript**](./typescript-support.mdx#typing-config)
|
||||
|
||||
Constraints:
|
||||
|
||||
- **Required:** use `export default /* your config*/` (or `module.exports` to export your Docusaurus config
|
||||
- **Optional:** use `import Lib from 'lib'` (or `require('lib')`) to import Node.js packages
|
||||
|
||||
:::
|
||||
|
||||
Node.js gives us the ability to declare our Docusaurus configuration in various **equivalent ways**, and all the following config examples lead to the exact same result:
|
||||
Docusaurus gives us the ability to declare its configuration in various **equivalent ways**, and all the following config examples lead to the exact same result:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
export default {
|
||||
title: 'Docusaurus',
|
||||
url: 'https://docusaurus.io',
|
||||
// your site config ...
|
||||
};
|
||||
```
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
|
@ -43,6 +56,16 @@ module.exports = {
|
|||
};
|
||||
```
|
||||
|
||||
```ts title="docusaurus.config.ts"
|
||||
import type {Config} from '@docusaurus/types';
|
||||
|
||||
export default {
|
||||
title: 'Docusaurus',
|
||||
url: 'https://docusaurus.io',
|
||||
// your site config ...
|
||||
} satisfies Config;
|
||||
```
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
const config = {
|
||||
title: 'Docusaurus',
|
||||
|
@ -50,27 +73,27 @@ const config = {
|
|||
// your site config ...
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
export default config;
|
||||
```
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = function configCreator() {
|
||||
export default function configCreator() {
|
||||
return {
|
||||
title: 'Docusaurus',
|
||||
url: 'https://docusaurus.io',
|
||||
// your site config ...
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = async function createConfigAsync() {
|
||||
export default async function createConfigAsync() {
|
||||
return {
|
||||
title: 'Docusaurus',
|
||||
url: 'https://docusaurus.io',
|
||||
// your site config ...
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
:::tip Using ESM-only packages
|
||||
|
@ -78,7 +101,7 @@ module.exports = async function createConfigAsync() {
|
|||
Using an async config creator can be useful to import ESM-only modules (notably most Remark plugins). It is possible to import such modules thanks to dynamic imports:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = async function createConfigAsync() {
|
||||
export default async function createConfigAsync() {
|
||||
// Use a dynamic import instead of require('esm-lib')
|
||||
// highlight-next-line
|
||||
const lib = await import('lib');
|
||||
|
@ -88,7 +111,7 @@ module.exports = async function createConfigAsync() {
|
|||
url: 'https://docusaurus.io',
|
||||
// rest of your site config...
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
@ -120,7 +143,7 @@ It is recommended to check the [deployment docs](deployment.mdx) for more inform
|
|||
List the [themes](./using-plugins.mdx#using-themes), [plugins](./using-plugins.mdx), and [presets](./using-plugins.mdx#using-presets) for your site in the `themes`, `plugins`, and `presets` fields, respectively. These are typically npm packages:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
'@docusaurus/plugin-content-blog',
|
||||
|
@ -135,7 +158,7 @@ module.exports = {
|
|||
Docusaurus supports [**module shorthands**](./using-plugins.mdx#module-shorthands), allowing you to simplify the above configuration as:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
plugins: ['content-blog', 'content-pages'],
|
||||
themes: ['classic'],
|
||||
|
@ -147,9 +170,9 @@ module.exports = {
|
|||
They can also be loaded from local directories:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
const path = require('path');
|
||||
import path from 'path';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
themes: [path.resolve(__dirname, '/path/to/docusaurus-local-theme')],
|
||||
};
|
||||
|
@ -158,7 +181,7 @@ module.exports = {
|
|||
To specify options for a plugin or theme, replace the name of the plugin or theme in the config file with an array containing the name and an options object:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
[
|
||||
|
@ -178,17 +201,17 @@ module.exports = {
|
|||
To specify options for a plugin or theme that is bundled in a preset, pass the options through the `presets` field. In this example, `docs` refers to `@docusaurus/plugin-content-docs` and `theme` refers to `@docusaurus/theme-classic`.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
{
|
||||
docs: {
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
sidebarPath: './sidebars.js',
|
||||
},
|
||||
theme: {
|
||||
customCss: [require.resolve('./src/css/custom.css')],
|
||||
customCss: ['./src/css/custom.css'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -211,7 +234,7 @@ Docusaurus guards `docusaurus.config.js` from unknown fields. To add custom fiel
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
// highlight-start
|
||||
customFields: {
|
||||
|
@ -255,8 +278,8 @@ If you just want to use those fields on the client side, you could create your o
|
|||
For new Docusaurus projects, we automatically generated a `babel.config.js` in the project root.
|
||||
|
||||
```js title="babel.config.js"
|
||||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
export default {
|
||||
presets: ['@docusaurus/core/lib/babel/preset'],
|
||||
};
|
||||
```
|
||||
|
||||
|
|
|
@ -61,9 +61,9 @@ Putting potentially sensitive information in the environment is common practice.
|
|||
|
||||
```js title="docusaurus.config.js"
|
||||
// If you are using dotenv (https://www.npmjs.com/package/dotenv)
|
||||
require('dotenv').config();
|
||||
import 'dotenv/config';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
title: '...',
|
||||
url: process.env.URL, // You can use environment variables to control site specifics as well
|
||||
// highlight-start
|
||||
|
@ -157,7 +157,7 @@ Because we can only provide this content on a best-effort basis only, we have st
|
|||
To deploy your Docusaurus 2 sites to [Netlify](https://www.netlify.com/), first make sure the following options are properly configured:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// highlight-start
|
||||
url: 'https://docusaurus-2.netlify.app', // Url to your site with no trailing slash
|
||||
baseUrl: '/', // Base directory of your site relative to your repo
|
||||
|
@ -263,7 +263,7 @@ GitHub Pages adds a trailing slash to Docusaurus URLs by default. It is recommen
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
url: 'https://endiliey.github.io', // Your website URL
|
||||
baseUrl: '/',
|
||||
|
|
|
@ -32,7 +32,7 @@ const SafeComponent = () => (
|
|||
```
|
||||
|
||||
```mdx-code-block
|
||||
import ErrorBoundaryTestButton from "@site/src/components/ErrorBoundaryTestButton"
|
||||
import ErrorBoundaryTestButton from '@site/src/components/ErrorBoundaryTestButton'
|
||||
```
|
||||
|
||||
:::tip
|
||||
|
|
|
@ -44,7 +44,7 @@ All docs will be served under the subroute `docs/`. But what if **your site only
|
|||
Assume that you have the following in your configuration:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
presets: [
|
||||
[
|
||||
|
@ -66,7 +66,7 @@ module.exports = {
|
|||
To enter docs-only mode, change it to like this:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
presets: [
|
||||
[
|
||||
|
|
|
@ -64,7 +64,7 @@ In this case, you should use the same plugin twice in your site configuration.
|
|||
When using the preset:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -75,7 +75,7 @@ module.exports = {
|
|||
// highlight-end
|
||||
path: 'product',
|
||||
routeBasePath: 'product',
|
||||
sidebarPath: require.resolve('./sidebarsProduct.js'),
|
||||
sidebarPath: './sidebarsProduct.js',
|
||||
// ... other options
|
||||
},
|
||||
},
|
||||
|
@ -90,7 +90,7 @@ module.exports = {
|
|||
// highlight-end
|
||||
path: 'community',
|
||||
routeBasePath: 'community',
|
||||
sidebarPath: require.resolve('./sidebarsCommunity.js'),
|
||||
sidebarPath: './sidebarsCommunity.js',
|
||||
// ... other options
|
||||
},
|
||||
],
|
||||
|
@ -101,7 +101,7 @@ module.exports = {
|
|||
When not using the preset:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-content-docs',
|
||||
|
@ -111,7 +111,7 @@ module.exports = {
|
|||
// highlight-end
|
||||
path: 'product',
|
||||
routeBasePath: 'product',
|
||||
sidebarPath: require.resolve('./sidebarsProduct.js'),
|
||||
sidebarPath: './sidebarsProduct.js',
|
||||
// ... other options
|
||||
},
|
||||
],
|
||||
|
@ -123,7 +123,7 @@ module.exports = {
|
|||
// highlight-end
|
||||
path: 'community',
|
||||
routeBasePath: 'community',
|
||||
sidebarPath: require.resolve('./sidebarsCommunity.js'),
|
||||
sidebarPath: './sidebarsCommunity.js',
|
||||
// ... other options
|
||||
},
|
||||
],
|
||||
|
@ -190,7 +190,7 @@ Each docs-related [theme navbar items](../../api/themes/theme-configuration.mdx#
|
|||
For example, if you want to have one version dropdown for each mobile SDK (iOS and Android), you could do:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
|
|
@ -21,7 +21,7 @@ type SidebarItemAutogenerated = {
|
|||
Docusaurus can generate a full sidebar from your docs folder:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
myAutogeneratedSidebar: [
|
||||
// highlight-start
|
||||
{
|
||||
|
@ -67,7 +67,7 @@ docs
|
|||
And assume every doc's ID is just its file name. If you define an autogenerated sidebar like this:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
mySidebar: [
|
||||
'intro',
|
||||
{
|
||||
|
@ -109,7 +109,7 @@ module.exports = {
|
|||
It would be resolved as:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
mySidebar: [
|
||||
'intro',
|
||||
{
|
||||
|
@ -175,7 +175,7 @@ A category index document is a document following one of those filename conventi
|
|||
This is equivalent to using a category with a [doc link](items.mdx#category-doc-link):
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
docs: [
|
||||
// highlight-start
|
||||
{
|
||||
|
@ -215,7 +215,7 @@ some-doc
|
|||
It is possible to opt out any of the category index conventions, or define even more conventions. You can inject your own `isCategoryIndex` matcher through the [`sidebarItemsGenerator`](#customize-the-sidebar-items-generator) callback. For example, you can also pick `intro` as another file name eligible for automatically becoming the category index.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-content-docs',
|
||||
|
@ -247,7 +247,7 @@ module.exports = {
|
|||
Or choose to not have any category index convention.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-content-docs',
|
||||
|
@ -426,7 +426,7 @@ Updating a number prefix can be annoying, as it can require **updating multiple
|
|||
You can provide a custom `sidebarItemsGenerator` function in the docs plugin (or preset) config:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-content-docs',
|
||||
|
@ -477,7 +477,7 @@ function reverseSidebarItems(items) {
|
|||
}
|
||||
// highlight-end
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-content-docs',
|
||||
|
|
|
@ -16,14 +16,14 @@ To use sidebars on your Docusaurus site:
|
|||
2. Pass this object into the `@docusaurus/plugin-docs` plugin directly or via `@docusaurus/preset-classic`.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
{
|
||||
docs: {
|
||||
// highlight-next-line
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
sidebarPath: './sidebars.js',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -44,7 +44,7 @@ import DocCardList from '@theme/DocCardList';
|
|||
If the `sidebarPath` is unspecified, Docusaurus [automatically generates a sidebar](autogenerated.mdx) for you, by using the filesystem structure of the `docs` folder:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
mySidebar: [
|
||||
{
|
||||
type: 'autogenerated',
|
||||
|
@ -71,7 +71,7 @@ type Sidebar =
|
|||
For example:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
mySidebar: [
|
||||
{
|
||||
type: 'category',
|
||||
|
@ -123,7 +123,7 @@ type SidebarsFile = {
|
|||
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 = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// highlight-start
|
||||
docs: {
|
||||
|
@ -141,7 +141,7 @@ module.exports = {
|
|||
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 = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// highlight-start
|
||||
docs: {
|
||||
|
@ -178,7 +178,7 @@ By default, breadcrumbs are rendered at the top, using the "sidebar path" of the
|
|||
This behavior can be disabled with plugin options:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -201,7 +201,7 @@ A real-world example from the Docusaurus site:
|
|||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
<CodeBlock language="js" title="sidebars.js">
|
||||
{require('!!raw-loader!@site/sidebars.js')
|
||||
{require('!!raw-loader!@site/sidebars.ts')
|
||||
.default
|
||||
.split('\n')
|
||||
// remove comments
|
||||
|
|
|
@ -42,7 +42,7 @@ type SidebarItemDoc =
|
|||
Example:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
mySidebar: [
|
||||
// Normal syntax:
|
||||
// highlight-start
|
||||
|
@ -92,7 +92,7 @@ type SidebarItemLink = {
|
|||
Example:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
myLinksSidebar: [
|
||||
// highlight-start
|
||||
// External link
|
||||
|
@ -133,7 +133,7 @@ type SidebarItemHtml = {
|
|||
Example:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
myHtmlSidebar: [
|
||||
// highlight-start
|
||||
{
|
||||
|
@ -151,7 +151,7 @@ module.exports = {
|
|||
The menu item is already wrapped in an `<li>` tag, so if your custom item is simple, such as a title, just supply a string as the value and use the `className` property to style it:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
myHtmlSidebar: [
|
||||
{
|
||||
type: 'html',
|
||||
|
@ -186,7 +186,7 @@ type SidebarItemCategory = {
|
|||
Example:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
docs: [
|
||||
{
|
||||
type: 'category',
|
||||
|
@ -211,7 +211,7 @@ module.exports = {
|
|||
Use the [**shorthand syntax**](#category-shorthand) when you don't need customizations:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
docs: {
|
||||
Guides: [
|
||||
'creating-pages',
|
||||
|
@ -242,7 +242,7 @@ Autogenerated categories can use the [`_category_.yml`](./autogenerated.mdx#cate
|
|||
You can auto-generate an index page that displays all the direct children of this category. The `slug` allows you to customize the generated page's route, which defaults to `/category/[categoryName]`.
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
docs: [
|
||||
{
|
||||
type: 'category',
|
||||
|
@ -276,7 +276,7 @@ Use `generated-index` links as a quick way to get an introductory document.
|
|||
A category can link to an existing document.
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
docs: [
|
||||
{
|
||||
type: 'category',
|
||||
|
@ -317,7 +317,7 @@ import DocCardList from '@theme/DocCardList';
|
|||
We support the option to expand/collapse categories. Categories are collapsible by default, but you can disable collapsing with `collapsible: false`.
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
docs: [
|
||||
{
|
||||
type: 'category',
|
||||
|
@ -340,7 +340,7 @@ module.exports = {
|
|||
To make all categories non-collapsible by default, set the `sidebarCollapsible` option in `plugin-content-docs` to `false`:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -366,7 +366,7 @@ The option in `sidebars.js` takes precedence over plugin configuration, so it is
|
|||
Collapsible categories are collapsed by default. If you want them to be expanded on the first render, you can set `collapsed` to `false`:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
docs: {
|
||||
Guides: [
|
||||
'creating-pages',
|
||||
|
@ -385,7 +385,7 @@ module.exports = {
|
|||
Similar to `collapsible`, you can also set the global configuration `options.sidebarCollapsed` to `false`. Individual `collapsed` options in `sidebars.js` will still take precedence over this configuration.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -420,7 +420,7 @@ An item with type `doc` can be simply a string representing its ID:
|
|||
```
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
sidebar: [
|
||||
// highlight-start
|
||||
{
|
||||
|
@ -438,7 +438,7 @@ module.exports = {
|
|||
```
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
sidebar: [
|
||||
// highlight-start
|
||||
'myDoc',
|
||||
|
@ -455,7 +455,7 @@ module.exports = {
|
|||
So it's possible to simplify the example above to:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
mySidebar: [
|
||||
{
|
||||
type: 'category',
|
||||
|
@ -494,7 +494,7 @@ A category item can be represented by an object whose key is its label, and the
|
|||
```
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
sidebar: [
|
||||
// highlight-start
|
||||
{
|
||||
|
@ -513,7 +513,7 @@ module.exports = {
|
|||
```
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
sidebar: [
|
||||
// highlight-start
|
||||
{
|
||||
|
@ -532,7 +532,7 @@ module.exports = {
|
|||
This permits us to simplify that example to:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
mySidebar: [
|
||||
// highlight-start
|
||||
{
|
||||
|
@ -554,7 +554,7 @@ module.exports = {
|
|||
Each shorthand object after this transformation will contain exactly one entry. Now consider the further simplified example below:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
mySidebar: [
|
||||
// highlight-start
|
||||
{
|
||||
|
@ -581,7 +581,7 @@ Wherever you have an array of items that is reduced to one category shorthand, y
|
|||
```
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
sidebar: [
|
||||
{
|
||||
'Getting started': ['doc1'],
|
||||
|
@ -602,7 +602,7 @@ module.exports = {
|
|||
```
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
sidebar: {
|
||||
'Getting started': ['doc1'],
|
||||
Docusaurus: {
|
||||
|
|
|
@ -18,7 +18,7 @@ The Docusaurus site is a good example of using multiple sidebars:
|
|||
Consider this example:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
tutorialSidebar: {
|
||||
'Category A': ['doc1', 'doc2'],
|
||||
},
|
||||
|
@ -33,7 +33,7 @@ When browsing `doc1` or `doc2`, the `tutorialSidebar` will be displayed; when br
|
|||
Following the example above, if a `commonDoc` is included in both sidebars:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
tutorialSidebar: {
|
||||
'Category A': ['doc1', 'doc2', 'commonDoc'],
|
||||
},
|
||||
|
@ -51,7 +51,7 @@ When you add doc Y to sidebar X, it creates a two-way binding: sidebar X contain
|
|||
Front matter option `displayed_sidebar` will forcibly set the sidebar association. For the same example, you can still use doc shorthands without any special configuration:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
tutorialSidebar: {
|
||||
'Category A': ['doc1', 'doc2'],
|
||||
},
|
||||
|
@ -88,7 +88,7 @@ If a sidebar is displayed by setting `displayed_sidebar` front matter, and this
|
|||
You can customize pagination with front matter `pagination_next` and `pagination_prev`. Consider this sidebar:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
tutorial: [
|
||||
'introduction',
|
||||
{
|
||||
|
@ -123,7 +123,7 @@ It is particularly useful where you wish to link to the same document from multi
|
|||
Consider this example:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
tutorialSidebar: {
|
||||
'Category A': [
|
||||
'doc1',
|
||||
|
@ -135,7 +135,6 @@ module.exports = {
|
|||
},
|
||||
apiSidebar: ['doc3', 'doc4', 'commonDoc'],
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
You can think of the `ref` type as the equivalent to doing the following:
|
||||
|
|
|
@ -187,7 +187,7 @@ Docusaurus defaults work great for the first use case. We will label the current
|
|||
**For the 2nd use case**: if you release v1 and don't plan to work on v2 anytime soon, instead of versioning v1 and having to maintain the docs in 2 folders (`./docs` + `./versioned_docs/version-1.0.0`), you may consider "pretending" that the current version is a cut version by giving it a path and a label:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
'@docusaurus/preset-classic',
|
||||
docs: {
|
||||
|
|
|
@ -275,7 +275,7 @@ export default function AdmonitionWrapper(props) {
|
|||
Admonitions are implemented with a [Remark plugin](./markdown-features-plugins.mdx). The plugin is designed to be configurable. To customize the Remark plugin for a specific content plugin (docs, blog, pages), pass the options through the `admonitions` key.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -306,7 +306,7 @@ By default, the theme doesn't know what do to with custom admonition keywords su
|
|||
If you registered a new admonition type `my-custom-admonition` via the following config:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
presets: [
|
||||
[
|
||||
|
|
|
@ -64,19 +64,19 @@ By default, the Prism [syntax highlighting theme](https://github.com/FormidableL
|
|||
For example, if you prefer to use the `dracula` highlighting theme:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
const {themes} = require('prism-react-renderer');
|
||||
import {themes as prismThemes} from 'prism-react-renderer';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
prism: {
|
||||
// highlight-next-line
|
||||
theme: themes.dracula,
|
||||
theme: prismThemes.dracula,
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Because a Prism theme is just a JS object, you can also write your own theme if you are not satisfied with the default. Docusaurus enhances the `github` and `vsDark` themes to provide richer highlight, and you can check our implementations for the [light](https://github.com/facebook/docusaurus/blob/main/website/src/utils/prismLight.mjs) and [dark](https://github.com/facebook/docusaurus/blob/main/website/src/utils/prismDark.mjs) code block themes.
|
||||
Because a Prism theme is just a JS object, you can also write your own theme if you are not satisfied with the default. Docusaurus enhances the `github` and `vsDark` themes to provide richer highlight, and you can check our implementations for the [light](https://github.com/facebook/docusaurus/blob/main/website/src/utils/prismLight.ts) and [dark](https://github.com/facebook/docusaurus/blob/main/website/src/utils/prismDark.ts) code block themes.
|
||||
|
||||
### Supported Languages {#supported-languages}
|
||||
|
||||
|
@ -99,7 +99,7 @@ Each additional language has to be a valid Prism component name. For example, Pr
|
|||
For example, if you want to add highlighting for the PowerShell language:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
themeConfig: {
|
||||
prism: {
|
||||
|
@ -301,7 +301,7 @@ You can declare custom magic comments through theme config. For example, you can
|
|||
```
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
prism: {
|
||||
magicComments: [
|
||||
|
@ -445,7 +445,7 @@ npm install --save @docusaurus/theme-live-codeblock
|
|||
You will also need to add the plugin to your `docusaurus.config.js`.
|
||||
|
||||
```js {3}
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
themes: ['@docusaurus/theme-live-codeblock'],
|
||||
// ...
|
||||
|
@ -758,7 +758,7 @@ npm install @docusaurus/remark-plugin-npm2yarn
|
|||
Docusaurus provides such a utility out of the box, freeing you from using the `Tabs` component every time. To enable this feature, first install the `@docusaurus/remark-plugin-npm2yarn` package as above, and then in `docusaurus.config.js`, for the plugins where you need this feature (doc, blog, pages, etc.), register it in the `remarkPlugins` option. (See [Docs configuration](../../api/plugins/plugin-content-docs.mdx#ex-config) for more details on configuration format)
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
presets: [
|
||||
[
|
||||
|
|
|
@ -18,7 +18,7 @@ npm install --save @docusaurus/theme-mermaid
|
|||
Enable Mermaid functionality by adding plugin `@docusaurus/theme-mermaid` and setting `markdown.mermaid` to `true` in your `docusaurus.config.js`.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
markdown: {
|
||||
mermaid: true,
|
||||
},
|
||||
|
@ -55,7 +55,7 @@ See the [Mermaid syntax documentation](https://mermaid-js.github.io/mermaid/#/./
|
|||
The diagram dark and light themes can be changed by setting `mermaid.theme` values in the `themeConfig` in your `docusaurus.config.js`. You can set themes for both light and dark mode.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
mermaid: {
|
||||
theme: {light: 'neutral', dark: 'forest'},
|
||||
|
@ -71,7 +71,7 @@ See the [Mermaid theme documentation](https://mermaid-js.github.io/mermaid/#/the
|
|||
Options in `mermaid.options` will be passed directly to `mermaid.initialize`:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
mermaid: {
|
||||
options: {
|
||||
|
|
|
@ -63,25 +63,63 @@ Make sure to use `remark-math >= 5` and `rehype-katex >= 6` for Docusaurus v3 (u
|
|||
|
||||
:::
|
||||
|
||||
Those 2 plugins are now only available as ESM packages, and you will need to import them dynamically.
|
||||
Those 2 plugins are now [**only available as ES Modules**](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). To simplify usage, it is recommended to use an [**ES Modules**](https://flaviocopes.com/es-modules/) config file:
|
||||
|
||||
First, turn your site config into an async config creator function:
|
||||
```js title="ES module docusaurus.config.js"
|
||||
// highlight-start
|
||||
import remarkMath from 'remark-math';
|
||||
import rehypeKatex from 'rehype-katex';
|
||||
// highlight-end
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = async function createConfigAsync() {
|
||||
return {
|
||||
// your site config...
|
||||
};
|
||||
// highlight-start
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
{
|
||||
docs: {
|
||||
path: 'docs',
|
||||
// highlight-start
|
||||
remarkPlugins: [remarkMath],
|
||||
rehypePlugins: [rehypeKatex],
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
It is now possible to import the plugins dynamically and add them to your content plugin or preset options (usually `@docusaurus/preset-classic` docs options):
|
||||
<details>
|
||||
<summary>Using a [**CommonJS**](https://nodejs.org/api/modules.html#modules-commonjs-modules) config file?</summary>
|
||||
|
||||
```js
|
||||
If you decide to use a CommonJS config file, it is possible to load those ES module plugins thanks to dynamic imports and an async config creator function:
|
||||
|
||||
```js title="CommonJS module docusaurus.config.js"
|
||||
// highlight-start
|
||||
module.exports = async function createConfigAsync() {
|
||||
// highlight-end
|
||||
return {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
{
|
||||
docs: {
|
||||
path: 'docs',
|
||||
// highlight-start
|
||||
remarkPlugins: [(await import('remark-math')).default],
|
||||
rehypePlugins: [(await import('rehype-katex')).default],
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Include the KaTeX CSS in your config under `stylesheets`:
|
||||
|
||||
```js
|
||||
|
@ -99,8 +137,12 @@ stylesheets: [
|
|||
Overall the changes look like:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = async function createConfigAsync() {
|
||||
return {
|
||||
// highlight-start
|
||||
import remarkMath from 'remark-math';
|
||||
import rehypeKatex from 'rehype-katex';
|
||||
// highlight-end
|
||||
|
||||
export default {
|
||||
title: 'Docusaurus',
|
||||
tagline: 'Build optimized websites quickly, focus on your content',
|
||||
presets: [
|
||||
|
@ -110,8 +152,8 @@ module.exports = async function createConfigAsync() {
|
|||
docs: {
|
||||
path: 'docs',
|
||||
// highlight-start
|
||||
remarkPlugins: [(await import('remark-math')).default],
|
||||
rehypePlugins: [(await import('rehype-katex')).default],
|
||||
remarkPlugins: [remarkMath],
|
||||
rehypePlugins: [rehypeKatex],
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
|
@ -129,7 +171,6 @@ module.exports = async function createConfigAsync() {
|
|||
],
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
## Self-hosting KaTeX assets {#self-hosting-katex-assets}
|
||||
|
@ -137,7 +178,7 @@ module.exports = async function createConfigAsync() {
|
|||
Loading stylesheets, fonts, and JavaScript libraries from CDN sources is a good practice for popular libraries and assets, since it reduces the amount of assets you have to host. In case you prefer to self-host the `katex.min.css` (along with required KaTeX fonts), you can download the latest version from [KaTeX GitHub releases](https://github.com/KaTeX/KaTeX/releases), extract and copy `katex.min.css` and `fonts` directory (only `.woff2` font types should be enough) to your site's `static` directory, and in `docusaurus.config.js`, replace the stylesheet's `href` from the CDN URL to your local path (say, `/katex/katex.min.css`).
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
stylesheets: [
|
||||
{
|
||||
href: '/katex/katex.min.css',
|
||||
|
|
|
@ -59,11 +59,41 @@ Next, the `rehype-katex` operates on the Hypertext AST where everything has been
|
|||
|
||||
:::warning
|
||||
|
||||
Many official Remark/Rehype plugins are using ES Modules, a new JavaScript module system, which Docusaurus doesn't support yet. To work around this issue, we recommend to use dynamic `import()` inside an `async` config creation function.
|
||||
Many official Remark/Rehype plugins are [**ES Modules only**](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c), a JavaScript module system, which Docusaurus supports. We recommend using an [**ES Modules**](https://flaviocopes.com/es-modules/) config file to make it easier to import such packages.
|
||||
|
||||
:::
|
||||
|
||||
Next, add them to the plugin options through plugin or preset config in `docusaurus.config.js`, using dynamic `import()`:
|
||||
Next, import your plugins and add them to the plugin options through plugin or preset config in `docusaurus.config.js`:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
// highlight-start
|
||||
import remarkMath from 'remark-math';
|
||||
import rehypeKatex from 'rehype-katex';
|
||||
// highlight-end
|
||||
|
||||
// highlight-start
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
{
|
||||
docs: {
|
||||
path: 'docs',
|
||||
// highlight-start
|
||||
remarkPlugins: [remarkMath],
|
||||
rehypePlugins: [rehypeKatex],
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Using a [**CommonJS**](https://nodejs.org/api/modules.html#modules-commonjs-modules) config file?</summary>
|
||||
|
||||
If you decide to use a CommonJS config file, it is possible to load those ES module plugins thanks to dynamic imports and an async config creator function:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
// highlight-start
|
||||
|
@ -88,13 +118,16 @@ module.exports = async function createConfigAsync() {
|
|||
};
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Configuring plugins {#configuring-plugins}
|
||||
|
||||
Some plugins can be configured and accept their own options. In that case, use the `[plugin, pluginOptions]` syntax, like this:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = async function createConfigAsync() {
|
||||
return {
|
||||
import rehypeKatex from 'rehype-katex';
|
||||
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -102,7 +135,7 @@ module.exports = async function createConfigAsync() {
|
|||
docs: {
|
||||
rehypePlugins: [
|
||||
// highlight-start
|
||||
[(await import('rehype-katex')).default, {strict: false}],
|
||||
[rehypeKatex, {strict: false}],
|
||||
// highlight-end
|
||||
],
|
||||
},
|
||||
|
@ -110,7 +143,6 @@ module.exports = async function createConfigAsync() {
|
|||
],
|
||||
],
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
You should check your plugin's documentation for the options it supports.
|
||||
|
@ -128,7 +160,7 @@ The writeup below is **not** meant to be a comprehensive guide to creating a plu
|
|||
For example, let's make a plugin that visits every `h2` heading and adds a `Section X. ` prefix. First, create your plugin source file anywhere—you can even publish it as a separate npm package and install it like explained above. We would put ours at `src/remark/section-prefix.js`. A remark/rehype plugin is just a function that receives the `options` and returns a `transformer` that operates on the AST.
|
||||
|
||||
```js "src/remark/section-prefix.js"
|
||||
const visit = require('unist-util-visit');
|
||||
import visit from 'unist-util-visit';
|
||||
|
||||
const plugin = (options) => {
|
||||
const transformer = async (ast) => {
|
||||
|
@ -146,16 +178,16 @@ const plugin = (options) => {
|
|||
return transformer;
|
||||
};
|
||||
|
||||
module.exports = plugin;
|
||||
export default plugin;
|
||||
```
|
||||
|
||||
You can now import your plugin in `docusaurus.config.js` and use it just like an installed plugin!
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
// highlight-next-line
|
||||
const sectionPrefix = require('./src/remark/section-prefix');
|
||||
import sectionPrefix from './src/remark/section-prefix';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -195,7 +227,7 @@ Our `transformImage` plugin uses this parameter, for example, to transform relat
|
|||
The default plugins of Docusaurus would operate before the custom remark plugins, and that means the images or links have been converted to JSX with `require()` calls already. For example, in the example above, the table of contents generated is still the same even when all `h2` headings are now prefixed by `Section X.`, because the TOC-generating plugin is called before our custom plugin. If you need to process the MDAST before the default plugins do, use the `beforeDefaultRemarkPlugins` and `beforeDefaultRehypePlugins`.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
|
|
@ -76,7 +76,7 @@ toc_max_heading_level: 5
|
|||
To set the heading level for _all_ pages, use the [`themeConfig.tableOfContents`](../../api/themes/theme-configuration.mdx#table-of-contents) option.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
tableOfContents: {
|
||||
// highlight-start
|
||||
|
|
|
@ -59,7 +59,7 @@ npx create-docusaurus@latest website classic
|
|||
Add the site configuration for the French language:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'fr'],
|
||||
|
@ -460,7 +460,7 @@ You may prefer the edit button to link to the Crowdin interface instead by using
|
|||
```js title="docusaurus.config.js"
|
||||
const DefaultLocale = 'en';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
|
|
@ -46,7 +46,7 @@ npx create-docusaurus@latest website classic
|
|||
Add the site configuration for the French language:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'fr'],
|
||||
|
|
|
@ -26,7 +26,7 @@ Modify `docusaurus.config.js` to add the i18n support for the French language.
|
|||
Use the [site i18n configuration](./../api/docusaurus.config.js.mdx#i18n) to declare the i18n locales:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'fr', 'fa'],
|
||||
|
@ -52,7 +52,7 @@ Docusaurus uses the locale names to provide **sensible defaults**: the `<html la
|
|||
Add a **navbar item** of type `localeDropdown` so that users can select the locale they want:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
|
|
|
@ -69,7 +69,7 @@ npm install --save @docusaurus/theme-search-algolia
|
|||
2. Register the theme in `docusaurus.config.js`:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
title: 'My site',
|
||||
// ...
|
||||
themes: ['@docusaurus/theme-search-algolia'],
|
||||
|
@ -84,7 +84,7 @@ module.exports = {
|
|||
Then, add an `algolia` field in your `themeConfig`. **[Apply for DocSearch](https://docsearch.algolia.com/apply/)** to get your Algolia index and API key.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
themeConfig: {
|
||||
// ...
|
||||
|
@ -146,7 +146,7 @@ Contextual search is **enabled by default**.
|
|||
It ensures that search results are **relevant to the current language and version**.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
themeConfig: {
|
||||
// ...
|
||||
|
@ -177,7 +177,7 @@ When using `contextualSearch: true` (default), the contextual facet filters will
|
|||
For specific needs, you can disable `contextualSearch` and define your own `facetFilters`:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
themeConfig: {
|
||||
// ...
|
||||
|
@ -252,7 +252,7 @@ Still, you can reuse the [Infima CSS variables](styling-layout.mdx#styling-your-
|
|||
Algolia DocSearch supports a [list of options](https://autocomplete-experimental.netlify.app/docs/DocSearchModal#reference) that you can pass to the `algolia` field in the `docusaurus.config.js` file.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// ...
|
||||
algolia: {
|
||||
|
|
|
@ -17,7 +17,7 @@ Docusaurus supports search engine optimization in a variety of ways.
|
|||
Provide global meta attributes for the entire site through the [site configuration](./configuration.mdx#site-metadata). The metadata will all be rendered in the HTML `<head>` using the key-value pairs as the prop name and value. The `metadata` attribute is a convenient shortcut to declare `<meta>` tags, but it is also possible to inject arbitrary tags in `<head>` with the `headTags` attribute.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themeConfig: {
|
||||
// Declare some <meta> tags
|
||||
metadata: [
|
||||
|
|
|
@ -16,7 +16,7 @@ This means that:
|
|||
You can customize the static directory sources in `docusaurus.config.js`. For example, we can add `public` as another possible path:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
title: 'My site',
|
||||
staticDirectories: ['public', 'static'],
|
||||
// ...
|
||||
|
|
|
@ -24,7 +24,7 @@ This is the most traditional way of styling that most developers (including non-
|
|||
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 = {
|
||||
export default {
|
||||
// ...
|
||||
presets: [
|
||||
[
|
||||
|
@ -32,7 +32,7 @@ module.exports = {
|
|||
{
|
||||
// highlight-start
|
||||
theme: {
|
||||
customCss: [require.resolve('./src/css/custom.css')],
|
||||
customCss: ['./src/css/custom.css'],
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
|
@ -234,7 +234,7 @@ npm install --save docusaurus-plugin-sass sass
|
|||
2. Include the plugin in your `docusaurus.config.js` file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
// highlight-next-line
|
||||
plugins: ['docusaurus-plugin-sass'],
|
||||
|
@ -249,7 +249,7 @@ module.exports = {
|
|||
You can now set the `customCss` property of `@docusaurus/preset-classic` to point to your Sass/SCSS file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -257,7 +257,7 @@ module.exports = {
|
|||
// ...
|
||||
theme: {
|
||||
// highlight-next-line
|
||||
customCss: [require.resolve('./src/css/custom.scss')],
|
||||
customCss: ['./src/css/custom.scss'],
|
||||
},
|
||||
// ...
|
||||
},
|
||||
|
|
|
@ -6,6 +6,8 @@ description: Docusaurus is written in TypeScript and provides first-class TypeSc
|
|||
|
||||
Docusaurus is written in TypeScript and provides first-class TypeScript support.
|
||||
|
||||
The minimum required version is **TypeScript 5.0**.
|
||||
|
||||
## Initialization {#initialization}
|
||||
|
||||
Docusaurus supports writing and using TypeScript theme components. If the init template provides a TypeScript variant, you can directly initialize a site with full TypeScript support by using the `--typescript` flag.
|
||||
|
@ -18,10 +20,10 @@ Below are some guides on how to migrate an existing project to TypeScript.
|
|||
|
||||
## Setup {#setup}
|
||||
|
||||
To start using TypeScript, add `@docusaurus/module-type-aliases` and the base TS config to your project:
|
||||
Add the following packages to your project:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install --save-dev typescript @docusaurus/module-type-aliases @docusaurus/tsconfig
|
||||
npm install --save-dev typescript @docusaurus/module-type-aliases @docusaurus/tsconfig @docusaurus/types
|
||||
```
|
||||
|
||||
Then add `tsconfig.json` to your project root with the following content:
|
||||
|
@ -41,69 +43,84 @@ Now you can start writing TypeScript theme components.
|
|||
|
||||
## Typing the config file {#typing-config}
|
||||
|
||||
It is **not possible** to use a TypeScript config file in Docusaurus unless you compile it yourself to JavaScript.
|
||||
It is possible to use a TypeScript config file in Docusaurus.
|
||||
|
||||
We recommend using [JSDoc type annotations](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html):
|
||||
```ts title="docusaurus.config.ts"
|
||||
import type {Config} from '@docusaurus/types';
|
||||
import type * as Preset from '@docusaurus/preset-classic';
|
||||
|
||||
// highlight-next-line
|
||||
const config: Config = {
|
||||
title: 'My Site',
|
||||
favicon: 'img/favicon.ico',
|
||||
|
||||
/* Your site config here */
|
||||
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
{
|
||||
/* Your preset config here */
|
||||
// highlight-next-line
|
||||
} satisfies Preset.Options,
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
/* Your theme config here */
|
||||
// highlight-next-line
|
||||
} satisfies Preset.ThemeConfig,
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>It is also possible to use [JSDoc type annotations](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html) within a `.js` file:</summary>
|
||||
|
||||
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 `npx tsc`.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
// highlight-next-line
|
||||
// @ts-check
|
||||
|
||||
// highlight-next-line
|
||||
/** @type {import('@docusaurus/types').Plugin} */
|
||||
function MyPlugin(context, options) {
|
||||
return {
|
||||
name: 'my-plugin',
|
||||
};
|
||||
}
|
||||
|
||||
// highlight-next-line
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
const config = {
|
||||
title: 'Docusaurus',
|
||||
tagline: 'Build optimized websites quickly, focus on your content',
|
||||
organizationName: 'facebook',
|
||||
projectName: 'docusaurus',
|
||||
plugins: [MyPlugin],
|
||||
tagline: 'Dinosaurs are cool',
|
||||
favicon: 'img/favicon.ico',
|
||||
|
||||
/* Your site config here */
|
||||
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
// highlight-next-line
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
({
|
||||
docs: {
|
||||
path: 'docs',
|
||||
sidebarPath: 'sidebars.js',
|
||||
},
|
||||
blog: {
|
||||
path: 'blog',
|
||||
postsPerPage: 5,
|
||||
},
|
||||
}),
|
||||
(
|
||||
{
|
||||
/* Your preset config here */
|
||||
}
|
||||
),
|
||||
],
|
||||
],
|
||||
themeConfig:
|
||||
// highlight-next-line
|
||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||
({
|
||||
colorMode: {
|
||||
defaultMode: 'dark',
|
||||
},
|
||||
navbar: {
|
||||
hideOnScroll: true,
|
||||
title: 'Docusaurus',
|
||||
logo: {
|
||||
alt: 'Docusaurus Logo',
|
||||
src: 'img/docusaurus.svg',
|
||||
srcDark: 'img/docusaurus_keytar.svg',
|
||||
},
|
||||
},
|
||||
}),
|
||||
(
|
||||
{
|
||||
/* Your theme config here */
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
export default config;
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
:::tip
|
||||
|
||||
Type annotations are very useful and help your IDE understand the type of config objects!
|
||||
|
@ -112,14 +129,6 @@ The best IDEs (VS Code, WebStorm, IntelliJ...) will provide a nice auto-completi
|
|||
|
||||
:::
|
||||
|
||||
:::info
|
||||
|
||||
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 `npx tsc`.
|
||||
|
||||
:::
|
||||
|
||||
## Swizzling TypeScript theme components {#swizzling-typescript-theme-components}
|
||||
|
||||
For themes that support TypeScript theme components, you can add the `--typescript` flag to the end of the `swizzle` command to get TypeScript source code. For example, the following command will generate `index.tsx` and `styles.module.css` into `src/theme/Footer`.
|
||||
|
|
|
@ -19,7 +19,7 @@ npm install --save docusaurus-plugin-name
|
|||
Then you add it in your site's `docusaurus.config.js`'s `plugins` option:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
// highlight-next-line
|
||||
plugins: ['@docusaurus/plugin-content-pages'],
|
||||
|
@ -29,7 +29,7 @@ module.exports = {
|
|||
Docusaurus can also load plugins from your local directory, with something like the following:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
// highlight-next-line
|
||||
plugins: ['./src/plugins/docusaurus-local-plugin'],
|
||||
|
@ -45,7 +45,7 @@ For the most basic usage of plugins, you can provide just the plugin name or the
|
|||
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".
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
// highlight-start
|
||||
|
@ -63,7 +63,7 @@ module.exports = {
|
|||
Example:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
// Basic usage.
|
||||
'@docusaurus/plugin-debug',
|
||||
|
@ -84,7 +84,7 @@ module.exports = {
|
|||
All Docusaurus content plugins can support multiple plugin instances. For example, it may be useful to have [multiple docs plugin instances](./guides/docs/docs-multi-instance.mdx) or [multiple blogs](./blog.mdx#multiple-blogs). It is required to assign a unique ID to each plugin instance, and by default, the plugin ID is `default`.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-content-docs',
|
||||
|
@ -123,7 +123,7 @@ The `themes` and `plugins` options lead to different [shorthand resolutions](#mo
|
|||
:::
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
// highlight-next-line
|
||||
themes: ['@docusaurus/theme-classic', '@docusaurus/theme-live-codeblock'],
|
||||
|
@ -152,7 +152,7 @@ The classic preset is shipped by default to new Docusaurus websites created with
|
|||
The classic preset will relay each option entry to the respective plugin/theme.
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
@ -161,7 +161,7 @@ module.exports = {
|
|||
debug: undefined,
|
||||
// Will be passed to @docusaurus/theme-classic.
|
||||
theme: {
|
||||
customCss: [require.resolve('./src/css/custom.css')],
|
||||
customCss: ['./src/css/custom.css'],
|
||||
},
|
||||
// Will be passed to @docusaurus/plugin-content-docs (false to disable)
|
||||
docs: {},
|
||||
|
@ -194,7 +194,7 @@ 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 = {
|
||||
export default {
|
||||
// ...
|
||||
// highlight-next-line
|
||||
presets: ['@docusaurus/preset-classic'],
|
||||
|
@ -204,7 +204,7 @@ module.exports = {
|
|||
Preset paths can be relative to the config file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
// ...
|
||||
// highlight-next-line
|
||||
presets: ['./src/presets/docusaurus-local-preset'],
|
||||
|
@ -216,7 +216,7 @@ module.exports = {
|
|||
A preset is a function with the same shape as the [plugin constructor](./api/plugin-methods/README.mdx#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 = {}) {
|
||||
export default function preset(context, opts = {}) {
|
||||
return {
|
||||
themes: [['docusaurus-theme-awesome', opts.theme]],
|
||||
plugins: [
|
||||
|
@ -227,13 +227,13 @@ module.exports = function preset(context, opts = {}) {
|
|||
['@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 = {
|
||||
export default {
|
||||
presets: [
|
||||
// highlight-start
|
||||
[
|
||||
|
@ -253,7 +253,7 @@ module.exports = {
|
|||
This is equivalent of doing:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
export default {
|
||||
themes: [['docusaurus-theme-awesome', {hello: 'world'}]],
|
||||
plugins: [
|
||||
['@docusaurus/plugin-content-docs', {id: 'docs1', path: '/docs'}],
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue