mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-11 16:17:25 +02:00
feat: async plugin creator functions (#6166)
This commit is contained in:
parent
f8a670966e
commit
b393700a61
17 changed files with 90 additions and 79 deletions
|
@ -103,7 +103,7 @@ describe('loadBlog', () => {
|
||||||
posixPath(path.relative(siteDir, p)),
|
posixPath(path.relative(siteDir, p)),
|
||||||
);
|
);
|
||||||
expect(relativePathsToWatch).toEqual([
|
expect(relativePathsToWatch).toEqual([
|
||||||
'blog/authors.yml',
|
'i18n/en/docusaurus-plugin-content-blog/authors.yml',
|
||||||
'i18n/en/docusaurus-plugin-content-blog/**/*.{md,mdx}',
|
'i18n/en/docusaurus-plugin-content-blog/**/*.{md,mdx}',
|
||||||
'blog/**/*.{md,mdx}',
|
'blog/**/*.{md,mdx}',
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -51,11 +51,12 @@ import {
|
||||||
} from './blogUtils';
|
} from './blogUtils';
|
||||||
import {BlogPostFrontMatter} from './blogFrontMatter';
|
import {BlogPostFrontMatter} from './blogFrontMatter';
|
||||||
import {createBlogFeedFiles} from './feed';
|
import {createBlogFeedFiles} from './feed';
|
||||||
|
import {getAuthorsMapFilePath} from './authors';
|
||||||
|
|
||||||
export default function pluginContentBlog(
|
export default async function pluginContentBlog(
|
||||||
context: LoadContext,
|
context: LoadContext,
|
||||||
options: PluginOptions,
|
options: PluginOptions,
|
||||||
): Plugin<BlogContent> {
|
): Promise<Plugin<BlogContent>> {
|
||||||
if (options.admonitions) {
|
if (options.admonitions) {
|
||||||
options.remarkPlugins = options.remarkPlugins.concat([
|
options.remarkPlugins = options.remarkPlugins.concat([
|
||||||
[admonitions, options.admonitions],
|
[admonitions, options.admonitions],
|
||||||
|
@ -89,24 +90,23 @@ export default function pluginContentBlog(
|
||||||
const aliasedSource = (source: string) =>
|
const aliasedSource = (source: string) =>
|
||||||
`~blog/${posixPath(path.relative(pluginDataDirRoot, source))}`;
|
`~blog/${posixPath(path.relative(pluginDataDirRoot, source))}`;
|
||||||
|
|
||||||
|
const authorsMapFilePath = await getAuthorsMapFilePath({
|
||||||
|
authorsMapPath: options.authorsMapPath,
|
||||||
|
contentPaths,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: 'docusaurus-plugin-content-blog',
|
name: 'docusaurus-plugin-content-blog',
|
||||||
|
|
||||||
getPathsToWatch() {
|
getPathsToWatch() {
|
||||||
const {include, authorsMapPath} = options;
|
const {include} = options;
|
||||||
const contentMarkdownGlobs = getContentPathList(contentPaths).flatMap(
|
const contentMarkdownGlobs = getContentPathList(contentPaths).flatMap(
|
||||||
(contentPath) => include.map((pattern) => `${contentPath}/${pattern}`),
|
(contentPath) => include.map((pattern) => `${contentPath}/${pattern}`),
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: we should read this path in plugin! but plugins do not support async init for now :'(
|
return [authorsMapFilePath, ...contentMarkdownGlobs].filter(
|
||||||
// const authorsMapFilePath = await getAuthorsMapFilePath({authorsMapPath,contentPaths,});
|
Boolean,
|
||||||
// simplified impl, better than nothing for now:
|
) as string[];
|
||||||
const authorsMapFilePath = path.join(
|
|
||||||
contentPaths.contentPath,
|
|
||||||
authorsMapPath,
|
|
||||||
);
|
|
||||||
|
|
||||||
return [authorsMapFilePath, ...contentMarkdownGlobs];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async getTranslationFiles() {
|
async getTranslationFiles() {
|
||||||
|
|
|
@ -115,7 +115,7 @@ describe('sidebar', () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
|
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const sidebarPath = path.join(siteDir, 'wrong-sidebars.json');
|
const sidebarPath = path.join(siteDir, 'wrong-sidebars.json');
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
sidebarPath,
|
sidebarPath,
|
||||||
|
@ -129,7 +129,7 @@ describe('sidebar', () => {
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
|
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
sidebarPath: 'wrong-path-sidebar.json',
|
sidebarPath: 'wrong-path-sidebar.json',
|
||||||
|
@ -148,7 +148,7 @@ describe('sidebar', () => {
|
||||||
test('site with undefined sidebar', async () => {
|
test('site with undefined sidebar', async () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-doc-label');
|
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-doc-label');
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
sidebarPath: undefined,
|
sidebarPath: undefined,
|
||||||
|
@ -177,7 +177,7 @@ describe('sidebar', () => {
|
||||||
test('site with disabled sidebar', async () => {
|
test('site with disabled sidebar', async () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-doc-label');
|
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-doc-label');
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
sidebarPath: false,
|
sidebarPath: false,
|
||||||
|
@ -196,7 +196,7 @@ describe('empty/no docs website', () => {
|
||||||
test('no files in docs folder', async () => {
|
test('no files in docs folder', async () => {
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
await fs.ensureDir(path.join(siteDir, 'docs'));
|
await fs.ensureDir(path.join(siteDir, 'docs'));
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {}),
|
normalizePluginOptions(OptionsSchema, {}),
|
||||||
);
|
);
|
||||||
|
@ -209,14 +209,14 @@ describe('empty/no docs website', () => {
|
||||||
|
|
||||||
test('docs folder does not exist', async () => {
|
test('docs folder does not exist', async () => {
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
expect(() =>
|
await expect(
|
||||||
pluginContentDocs(
|
pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
path: `path/doesnt/exist`,
|
path: `path/doesnt/exist`,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
).toThrowError(
|
).rejects.toThrowError(
|
||||||
`The docs folder does not exist for version "current". A docs folder is expected to be found at ${
|
`The docs folder does not exist for version "current". A docs folder is expected to be found at ${
|
||||||
process.platform === 'win32'
|
process.platform === 'win32'
|
||||||
? 'path\\doesnt\\exist'
|
? 'path\\doesnt\\exist'
|
||||||
|
@ -231,7 +231,7 @@ describe('simple website', () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
|
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
path: 'docs',
|
path: 'docs',
|
||||||
|
@ -349,7 +349,7 @@ describe('versioned website', () => {
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
||||||
const routeBasePath = 'docs';
|
const routeBasePath = 'docs';
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
routeBasePath,
|
routeBasePath,
|
||||||
|
@ -494,7 +494,7 @@ describe('versioned website (community)', () => {
|
||||||
const sidebarPath = path.join(siteDir, 'community_sidebars.json');
|
const sidebarPath = path.join(siteDir, 'community_sidebars.json');
|
||||||
const routeBasePath = 'community';
|
const routeBasePath = 'community';
|
||||||
const pluginId = 'community';
|
const pluginId = 'community';
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
id: 'community',
|
id: 'community',
|
||||||
|
@ -607,7 +607,7 @@ describe('site with doc label', () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-doc-label');
|
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-doc-label');
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
path: 'docs',
|
path: 'docs',
|
||||||
|
@ -645,7 +645,7 @@ describe('site with full autogenerated sidebar', () => {
|
||||||
'site-with-autogenerated-sidebar',
|
'site-with-autogenerated-sidebar',
|
||||||
);
|
);
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
path: 'docs',
|
path: 'docs',
|
||||||
|
@ -697,7 +697,7 @@ describe('site with partial autogenerated sidebars', () => {
|
||||||
'site-with-autogenerated-sidebar',
|
'site-with-autogenerated-sidebar',
|
||||||
);
|
);
|
||||||
const context = await loadContext(siteDir, {});
|
const context = await loadContext(siteDir, {});
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
path: 'docs',
|
path: 'docs',
|
||||||
|
@ -749,7 +749,7 @@ describe('site with partial autogenerated sidebars 2 (fix #4638)', () => {
|
||||||
'site-with-autogenerated-sidebar',
|
'site-with-autogenerated-sidebar',
|
||||||
);
|
);
|
||||||
const context = await loadContext(siteDir, {});
|
const context = await loadContext(siteDir, {});
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
path: 'docs',
|
path: 'docs',
|
||||||
|
@ -783,7 +783,7 @@ describe('site with custom sidebar items generator', () => {
|
||||||
'site-with-autogenerated-sidebar',
|
'site-with-autogenerated-sidebar',
|
||||||
);
|
);
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const plugin = pluginContentDocs(
|
const plugin = await pluginContentDocs(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions(OptionsSchema, {
|
normalizePluginOptions(OptionsSchema, {
|
||||||
path: 'docs',
|
path: 'docs',
|
||||||
|
|
|
@ -58,10 +58,10 @@ import type {PropTagsListPage} from '@docusaurus/plugin-content-docs';
|
||||||
import {createSidebarsUtils} from './sidebars/utils';
|
import {createSidebarsUtils} from './sidebars/utils';
|
||||||
import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
|
import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
|
||||||
|
|
||||||
export default function pluginContentDocs(
|
export default async function pluginContentDocs(
|
||||||
context: LoadContext,
|
context: LoadContext,
|
||||||
options: PluginOptions,
|
options: PluginOptions,
|
||||||
): Plugin<LoadedContent> {
|
): Promise<Plugin<LoadedContent>> {
|
||||||
const {siteDir, generatedFilesDir, baseUrl, siteConfig} = context;
|
const {siteDir, generatedFilesDir, baseUrl, siteConfig} = context;
|
||||||
|
|
||||||
const versionsMetadata = readVersionsMetadata({context, options});
|
const versionsMetadata = readVersionsMetadata({context, options});
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"@docusaurus/mdx-loader": "2.0.0-beta.14",
|
"@docusaurus/mdx-loader": "2.0.0-beta.14",
|
||||||
"@docusaurus/utils": "2.0.0-beta.14",
|
"@docusaurus/utils": "2.0.0-beta.14",
|
||||||
"@docusaurus/utils-validation": "2.0.0-beta.14",
|
"@docusaurus/utils-validation": "2.0.0-beta.14",
|
||||||
|
"fs-extra": "^10.0.0",
|
||||||
"globby": "^11.0.2",
|
"globby": "^11.0.2",
|
||||||
"remark-admonitions": "^1.2.1",
|
"remark-admonitions": "^1.2.1",
|
||||||
"tslib": "^2.3.1",
|
"tslib": "^2.3.1",
|
||||||
|
|
|
@ -16,7 +16,7 @@ describe('docusaurus-plugin-content-pages', () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'website');
|
const siteDir = path.join(__dirname, '__fixtures__', 'website');
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const pluginPath = 'src/pages';
|
const pluginPath = 'src/pages';
|
||||||
const plugin = pluginContentPages(
|
const plugin = await pluginContentPages(
|
||||||
context,
|
context,
|
||||||
normalizePluginOptions({
|
normalizePluginOptions({
|
||||||
path: pluginPath,
|
path: pluginPath,
|
||||||
|
@ -77,7 +77,7 @@ describe('docusaurus-plugin-content-pages', () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'website');
|
const siteDir = path.join(__dirname, '__fixtures__', 'website');
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const pluginPath = 'src/pages';
|
const pluginPath = 'src/pages';
|
||||||
const plugin = pluginContentPages(
|
const plugin = await pluginContentPages(
|
||||||
{
|
{
|
||||||
...context,
|
...context,
|
||||||
i18n: {
|
i18n: {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'fs';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import {
|
import {
|
||||||
encodePath,
|
encodePath,
|
||||||
|
@ -45,10 +45,10 @@ export function getContentPathList(contentPaths: PagesContentPaths): string[] {
|
||||||
const isMarkdownSource = (source: string) =>
|
const isMarkdownSource = (source: string) =>
|
||||||
source.endsWith('.md') || source.endsWith('.mdx');
|
source.endsWith('.md') || source.endsWith('.mdx');
|
||||||
|
|
||||||
export default function pluginContentPages(
|
export default async function pluginContentPages(
|
||||||
context: LoadContext,
|
context: LoadContext,
|
||||||
options: PluginOptions,
|
options: PluginOptions,
|
||||||
): Plugin<LoadedContent | null> {
|
): Promise<Plugin<LoadedContent | null>> {
|
||||||
if (options.admonitions) {
|
if (options.admonitions) {
|
||||||
options.remarkPlugins = options.remarkPlugins.concat([
|
options.remarkPlugins = options.remarkPlugins.concat([
|
||||||
[admonitions, options.admonitions || {}],
|
[admonitions, options.admonitions || {}],
|
||||||
|
@ -90,7 +90,7 @@ export default function pluginContentPages(
|
||||||
async loadContent() {
|
async loadContent() {
|
||||||
const {include} = options;
|
const {include} = options;
|
||||||
|
|
||||||
if (!fs.existsSync(contentPaths.contentPath)) {
|
if (!(await fs.pathExists(contentPaths.contentPath))) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
packages/docusaurus-types/src/index.d.ts
vendored
4
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -317,7 +317,9 @@ export type LoadedPlugin<Content = unknown> = InitializedPlugin<Content> & {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PluginModule = {
|
export type PluginModule = {
|
||||||
<T, X>(context: LoadContext, options: T): Plugin<X>;
|
<Options, Content>(context: LoadContext, options: Options):
|
||||||
|
| Plugin<Content>
|
||||||
|
| Promise<Plugin<Content>>;
|
||||||
validateOptions?: <T>(data: OptionValidationContext<T>) => T;
|
validateOptions?: <T>(data: OptionValidationContext<T>) => T;
|
||||||
validateThemeConfig?: <T>(data: ThemeConfigValidationContext<T>) => T;
|
validateThemeConfig?: <T>(data: ThemeConfigValidationContext<T>) => T;
|
||||||
getSwizzleComponentList?: () => string[];
|
getSwizzleComponentList?: () => string[];
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default async function externalCommand(
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const pluginConfigs = loadPluginConfigs(context);
|
const pluginConfigs = loadPluginConfigs(context);
|
||||||
const plugins = initPlugins({pluginConfigs, context});
|
const plugins = await initPlugins({pluginConfigs, context});
|
||||||
|
|
||||||
// Plugin Lifecycle - extendCli.
|
// Plugin Lifecycle - extendCli.
|
||||||
plugins.forEach((plugin) => {
|
plugins.forEach((plugin) => {
|
||||||
|
|
|
@ -149,7 +149,7 @@ export default async function swizzle(
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const pluginConfigs = loadPluginConfigs(context);
|
const pluginConfigs = loadPluginConfigs(context);
|
||||||
const pluginNames = getPluginNames(pluginConfigs);
|
const pluginNames = getPluginNames(pluginConfigs);
|
||||||
const plugins = initPlugins({
|
const plugins = await initPlugins({
|
||||||
pluginConfigs,
|
pluginConfigs,
|
||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
|
@ -209,7 +209,7 @@ export default async function swizzle(
|
||||||
|
|
||||||
// support both commonjs and ES style exports
|
// support both commonjs and ES style exports
|
||||||
const plugin = pluginModule.default ?? pluginModule;
|
const plugin = pluginModule.default ?? pluginModule;
|
||||||
const pluginInstance = plugin(context, pluginOptions);
|
const pluginInstance = await plugin(context, pluginOptions);
|
||||||
const themePath = typescript
|
const themePath = typescript
|
||||||
? pluginInstance.getTypeScriptThemePath?.()
|
? pluginInstance.getTypeScriptThemePath?.()
|
||||||
: pluginInstance.getThemePath?.();
|
: pluginInstance.getThemePath?.();
|
||||||
|
|
|
@ -124,7 +124,7 @@ async function transformMarkdownFile(
|
||||||
async function getPathsToWatch(siteDir: string): Promise<string[]> {
|
async function getPathsToWatch(siteDir: string): Promise<string[]> {
|
||||||
const context = await loadContext(siteDir);
|
const context = await loadContext(siteDir);
|
||||||
const pluginConfigs = loadPluginConfigs(context);
|
const pluginConfigs = loadPluginConfigs(context);
|
||||||
const plugins = initPlugins({
|
const plugins = await initPlugins({
|
||||||
pluginConfigs,
|
pluginConfigs,
|
||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
|
|
|
@ -78,7 +78,7 @@ export default async function writeTranslations(
|
||||||
locale: options.locale,
|
locale: options.locale,
|
||||||
});
|
});
|
||||||
const pluginConfigs = loadPluginConfigs(context);
|
const pluginConfigs = loadPluginConfigs(context);
|
||||||
const plugins = initPlugins({
|
const plugins = await initPlugins({
|
||||||
pluginConfigs,
|
pluginConfigs,
|
||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@ describe('initPlugins', () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-plugin');
|
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-plugin');
|
||||||
const context = await loadContext(siteDir, options);
|
const context = await loadContext(siteDir, options);
|
||||||
const pluginConfigs = loadPluginConfigs(context);
|
const pluginConfigs = loadPluginConfigs(context);
|
||||||
const plugins = initPlugins({
|
const plugins = await initPlugins({
|
||||||
pluginConfigs,
|
pluginConfigs,
|
||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
|
|
|
@ -78,7 +78,7 @@ export async function loadPlugins({
|
||||||
themeConfigTranslated: ThemeConfig;
|
themeConfigTranslated: ThemeConfig;
|
||||||
}> {
|
}> {
|
||||||
// 1. Plugin Lifecycle - Initialization/Constructor.
|
// 1. Plugin Lifecycle - Initialization/Constructor.
|
||||||
const plugins: InitializedPlugin[] = initPlugins({
|
const plugins: InitializedPlugin[] = await initPlugins({
|
||||||
pluginConfigs,
|
pluginConfigs,
|
||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
|
|
|
@ -124,13 +124,13 @@ function getThemeValidationFunction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function initPlugins({
|
export default async function initPlugins({
|
||||||
pluginConfigs,
|
pluginConfigs,
|
||||||
context,
|
context,
|
||||||
}: {
|
}: {
|
||||||
pluginConfigs: PluginConfig[];
|
pluginConfigs: PluginConfig[];
|
||||||
context: LoadContext;
|
context: LoadContext;
|
||||||
}): InitializedPlugin[] {
|
}): Promise<InitializedPlugin[]> {
|
||||||
// We need to resolve plugins from the perspective of the siteDir, since the siteDir's package.json
|
// We need to resolve plugins from the perspective of the siteDir, since the siteDir's package.json
|
||||||
// declares the dependency on these plugins.
|
// declares the dependency on these plugins.
|
||||||
const pluginRequire = createRequire(context.siteConfigPath);
|
const pluginRequire = createRequire(context.siteConfigPath);
|
||||||
|
@ -184,37 +184,45 @@ export default function initPlugins({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const plugins: InitializedPlugin[] = pluginConfigs
|
async function initializePlugin(
|
||||||
.map((pluginConfig) => {
|
pluginConfig: PluginConfig,
|
||||||
if (!pluginConfig) {
|
): Promise<InitializedPlugin> {
|
||||||
return null;
|
const normalizedPluginConfig = normalizePluginConfig(
|
||||||
}
|
pluginConfig,
|
||||||
const normalizedPluginConfig = normalizePluginConfig(
|
pluginRequire,
|
||||||
pluginConfig,
|
);
|
||||||
pluginRequire,
|
const pluginVersion: DocusaurusPluginVersionInformation =
|
||||||
);
|
doGetPluginVersion(normalizedPluginConfig);
|
||||||
const pluginVersion: DocusaurusPluginVersionInformation =
|
const pluginOptions = doValidatePluginOptions(normalizedPluginConfig);
|
||||||
doGetPluginVersion(normalizedPluginConfig);
|
|
||||||
const pluginOptions = doValidatePluginOptions(normalizedPluginConfig);
|
|
||||||
|
|
||||||
// Side-effect: merge the normalized theme config in the original one
|
// Side-effect: merge the normalized theme config in the original one
|
||||||
context.siteConfig.themeConfig = {
|
context.siteConfig.themeConfig = {
|
||||||
...context.siteConfig.themeConfig,
|
...context.siteConfig.themeConfig,
|
||||||
...doValidateThemeConfig(normalizedPluginConfig),
|
...doValidateThemeConfig(normalizedPluginConfig),
|
||||||
};
|
};
|
||||||
|
|
||||||
const pluginInstance = normalizedPluginConfig.plugin(
|
const pluginInstance = await normalizedPluginConfig.plugin(
|
||||||
context,
|
context,
|
||||||
pluginOptions,
|
pluginOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...pluginInstance,
|
...pluginInstance,
|
||||||
options: pluginOptions,
|
options: pluginOptions,
|
||||||
version: pluginVersion,
|
version: pluginVersion,
|
||||||
};
|
};
|
||||||
})
|
}
|
||||||
.filter(<T>(item: T): item is Exclude<T, null> => Boolean(item));
|
|
||||||
|
const plugins: InitializedPlugin[] = (
|
||||||
|
await Promise.all(
|
||||||
|
pluginConfigs.map((pluginConfig) => {
|
||||||
|
if (!pluginConfig) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return initializePlugin(pluginConfig);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
).filter(<T>(item: T): item is Exclude<T, null> => Boolean(item));
|
||||||
|
|
||||||
ensureUniquePluginInstanceIds(plugins);
|
ensureUniquePluginInstanceIds(plugins);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ Every plugin is imported as a module. The module is expected to have the followi
|
||||||
|
|
||||||
## Plugin constructor
|
## Plugin constructor
|
||||||
|
|
||||||
The plugin module's default export is a constructor function with the signature `(context: LoadContext, options: PluginOptions) => Plugin`.
|
The plugin module's default export is a constructor function with the signature `(context: LoadContext, options: PluginOptions) => Plugin | Promise<Plugin>`.
|
||||||
|
|
||||||
### `context` {#context}
|
### `context` {#context}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ Here's a mind model for a presumptuous plugin implementation.
|
||||||
// A JavaScript function that returns an object.
|
// A JavaScript function that returns an object.
|
||||||
// `context` is provided by Docusaurus. Example: siteConfig can be accessed from context.
|
// `context` is provided by Docusaurus. Example: siteConfig can be accessed from context.
|
||||||
// `opts` is the user-defined options.
|
// `opts` is the user-defined options.
|
||||||
function myPlugin(context, opts) {
|
async function myPlugin(context, opts) {
|
||||||
return {
|
return {
|
||||||
// A compulsory field used as the namespace for directories to cache
|
// A compulsory field used as the namespace for directories to cache
|
||||||
// the intermediate data for each plugin.
|
// the intermediate data for each plugin.
|
||||||
|
|
|
@ -119,7 +119,7 @@ Docusaurus' implementation of the plugins system provides us with a convenient w
|
||||||
|
|
||||||
## Creating plugins {#creating-plugins}
|
## Creating plugins {#creating-plugins}
|
||||||
|
|
||||||
A plugin is a function that takes two parameters: `context` and `options`. It returns a plugin instance object. You can create plugins as functions or modules. For more information, refer to the [plugin method references section](./api/plugin-methods/README.md).
|
A plugin is a function that takes two parameters: `context` and `options`. It returns a plugin instance object (or a promise). You can create plugins as functions or modules. For more information, refer to the [plugin method references section](./api/plugin-methods/README.md).
|
||||||
|
|
||||||
### Functional definition {#functional-definition}
|
### Functional definition {#functional-definition}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ module.exports = {
|
||||||
// ...
|
// ...
|
||||||
plugins: [
|
plugins: [
|
||||||
// highlight-start
|
// highlight-start
|
||||||
function myPlugin(context, options) {
|
async function myPlugin(context, options) {
|
||||||
// ...
|
// ...
|
||||||
return {
|
return {
|
||||||
name: 'my-plugin',
|
name: 'my-plugin',
|
||||||
|
@ -167,7 +167,7 @@ module.exports = {
|
||||||
Then in the folder `my-plugin` you can create an index.js such as this:
|
Then in the folder `my-plugin` you can create an index.js such as this:
|
||||||
|
|
||||||
```js title="my-plugin.js"
|
```js title="my-plugin.js"
|
||||||
module.exports = function myPlugin(context, options) {
|
module.exports = async function myPlugin(context, options) {
|
||||||
// ...
|
// ...
|
||||||
return {
|
return {
|
||||||
name: 'my-plugin',
|
name: 'my-plugin',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue