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:
Chongyi Zheng 2023-10-13 20:46:03 -04:00 committed by GitHub
parent 336a44f3ea
commit 45f1a669b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
126 changed files with 2054 additions and 914 deletions

View file

@ -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;
}
```

View file

@ -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,15 +118,15 @@ 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 = [
'CodeBlock',
'DocSidebar',
'Footer',
'NotFound',
'SearchBar',
'hooks/useTheme',
'prism-include-languages',
];
myTheme.getSwizzleComponentList = () => swizzleAllowedComponents;
export function getSwizzleComponentList() {
return [
'CodeBlock',
'DocSidebar',
'Footer',
'NotFound',
'SearchBar',
'hooks/useTheme',
'prism-include-languages',
];
}
```

View file

@ -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
};
};
}
```

View file

@ -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
};
};
}
```

View file

@ -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