diff --git a/packages/docusaurus/src/commands/start.ts b/packages/docusaurus/src/commands/start.ts index 6bc6e78ad0..568a777996 100644 --- a/packages/docusaurus/src/commands/start.ts +++ b/packages/docusaurus/src/commands/start.ts @@ -59,7 +59,7 @@ export async function start( }; const pluginPaths = _.compact( - _.flatten( + _.flatten( plugins.map(plugin => plugin.getPathsToWatch && plugin.getPathsToWatch()), ), ).map(normalizeToSiteDir); diff --git a/packages/docusaurus/src/server/config.ts b/packages/docusaurus/src/server/config.ts index 4061330b05..5f755b3488 100644 --- a/packages/docusaurus/src/server/config.ts +++ b/packages/docusaurus/src/server/config.ts @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +import {PluginConfig} from './plugins'; + import fs from 'fs-extra'; import _ from 'lodash'; import importFresh from 'import-fresh'; @@ -21,7 +23,7 @@ export interface DocusaurusConfig { projectName?: string; customFields?: string[]; githubHost?: string; - plugins?: any[]; + plugins?: PluginConfig[]; presets?: any[]; themeConfig?: { [key: string]: any; diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts index 6539501f10..a834fc4a03 100644 --- a/packages/docusaurus/src/server/index.ts +++ b/packages/docusaurus/src/server/index.ts @@ -5,7 +5,11 @@ * LICENSE file in the root directory of this source tree. */ +import {PluginConfig, Plugin} from './plugins'; + import path from 'path'; +import _ from 'lodash'; + import {generate} from '@docusaurus/utils'; import {loadConfig, DocusaurusConfig} from './config'; @@ -29,7 +33,7 @@ export interface LoadContext { } export interface Props extends LoadContext { routesPaths: string[]; - plugins: any[]; + plugins: Plugin[]; } export async function load( @@ -60,11 +64,11 @@ export async function load( baseUrl, }; - /* Preset */ + // Presets. const {plugins: presetPlugins, themes: presetThemes} = loadPresets(context); - /* Plugin */ - const pluginConfigs = [ + // Plugins. + const pluginConfigs: PluginConfig[] = [ ...presetPlugins, ...(siteConfig.plugins || []), ...presetThemes, @@ -75,15 +79,16 @@ export async function load( context, }); - /* Theme */ + // Themes. const fallbackTheme = path.resolve(__dirname, '../client/theme-fallback'); - const pluginThemes = plugins - .map(plugin => plugin.getThemePath && plugin.getThemePath()) - .filter(Boolean) as string[]; + const pluginThemes = _.compact( + plugins.map(plugin => plugin.getThemePath && plugin.getThemePath()), + ); const userTheme = path.resolve(siteDir, 'theme'); const alias = loadThemeAlias([fallbackTheme, ...pluginThemes, userTheme]); // Make a fake plugin to resolve aliased theme components. plugins.push({ + name: 'docusaurus-bootstrap-plugin', configureWebpack: () => ({ resolve: { alias, diff --git a/packages/docusaurus/src/server/plugins/index.ts b/packages/docusaurus/src/server/plugins/index.ts index 334ab55146..d3e99381fc 100644 --- a/packages/docusaurus/src/server/plugins/index.ts +++ b/packages/docusaurus/src/server/plugins/index.ts @@ -5,21 +5,51 @@ * LICENSE file in the root directory of this source tree. */ +import {LoadContext, Props} from '..'; +import {RouteConfig} from '../routes'; + import fs from 'fs-extra'; import importFresh from 'import-fresh'; import path from 'path'; import {generate} from '@docusaurus/utils'; -import {LoadContext} from '..'; +import {Configuration} from 'webpack'; + +export interface Plugin { + name: string; + loadContent?(): T; + contentLoaded?({ + content: T, + actions: DocusaurusPluginContentLoadedActions, + }): void; + postBuild?(props: Props): void; + postStart?(props: Props): void; + configureWebpack?(config: Configuration, isServer: boolean): Configuration; + getThemePath?(): string; + getPathsToWatch?(): string[]; +} + +export interface PluginConfig { + module: string; + options?: Object; +} + +export interface PluginContentLoadedActions { + addRoute(config: RouteConfig): void; + createData(name: string, data: Object): Promise; +} export async function loadPlugins({ - pluginConfigs = [], + pluginConfigs, context, }: { - pluginConfigs: any[]; + pluginConfigs: PluginConfig[]; context: LoadContext; -}) { +}): Promise<{ + plugins: Plugin[]; + pluginsRouteConfigs: RouteConfig[]; +}> { // 1. Plugin Lifecycle - Initialization/Constructor - const plugins = pluginConfigs.map(({module, options}) => { + const plugins: Plugin[] = pluginConfigs.map(({module, options}) => { // module is any valid module identifier - npm package or locally-resolved path. const plugin = importFresh(module); return plugin(context, options); @@ -40,7 +70,7 @@ export async function loadPlugins({ ); // 3. Plugin lifecycle - contentLoaded - const pluginsRouteConfigs: any[] = []; + const pluginsRouteConfigs: RouteConfig[] = []; await Promise.all( plugins.map(async (plugin, index) => { @@ -52,7 +82,8 @@ export async function loadPlugins({ context.generatedFilesDir, plugin.name, ); - const actions = { + + const actions: PluginContentLoadedActions = { addRoute: config => pluginsRouteConfigs.push(config), createData: async (name, content) => { const modulePath = path.join(pluginContentDir, name); @@ -62,9 +93,8 @@ export async function loadPlugins({ }, }; - const loadedContent = pluginsLoadedContent[index]; await plugin.contentLoaded({ - content: loadedContent, + content: pluginsLoadedContent[index], actions, }); }), diff --git a/packages/docusaurus/src/server/presets/index.ts b/packages/docusaurus/src/server/presets/index.ts index 49c27034b6..84c67ed983 100644 --- a/packages/docusaurus/src/server/presets/index.ts +++ b/packages/docusaurus/src/server/presets/index.ts @@ -5,31 +5,45 @@ * LICENSE file in the root directory of this source tree. */ +import {LoadContext} from '../index'; +import {PluginConfig} from '../plugins'; + import importFresh from 'import-fresh'; import _ from 'lodash'; -import {LoadContext} from '../index'; -export function loadPresets(context: LoadContext) { +export interface Preset { + plugins?: PluginConfig[]; + themes?: PluginConfig[]; +} + +export function loadPresets( + context: LoadContext, +): { + plugins: PluginConfig[]; + themes: PluginConfig[]; +} { const presets: any[] = context.siteConfig.presets || []; - const plugins: any[] = []; - const themes: any[] = []; + const plugins: (PluginConfig[] | undefined)[] = []; + const themes: (PluginConfig[] | undefined)[] = []; presets.forEach(presetItem => { - let presetModule; + let presetModuleImport; let presetOptions = {}; if (typeof presetItem === 'string') { - presetModule = presetItem; + presetModuleImport = presetItem; } else if (Array.isArray(presetItem)) { - [presetModule, presetOptions] = presetItem; + [presetModuleImport, presetOptions] = presetItem; } - const preset = importFresh(presetModule); - plugins.push(preset(context, presetOptions).plugins); - themes.push(preset(context, presetOptions).themes); + const presetModule = importFresh(presetModuleImport); + const preset: Preset = presetModule(context, presetOptions); + + plugins.push(preset.plugins); + themes.push(preset.themes); }); return { - plugins: _.compact(_.flatten(plugins)), - themes: _.compact(_.flatten(themes)), + plugins: _.compact(_.flatten(plugins)), + themes: _.compact(_.flatten(themes)), }; } diff --git a/packages/docusaurus/src/server/themes/alias.ts b/packages/docusaurus/src/server/themes/alias.ts index 2435d90cb7..1cdb5635f7 100644 --- a/packages/docusaurus/src/server/themes/alias.ts +++ b/packages/docusaurus/src/server/themes/alias.ts @@ -10,11 +10,11 @@ import fs from 'fs-extra'; import path from 'path'; import {fileToPath, posixPath, normalizeUrl} from '@docusaurus/utils'; -export interface Alias { +export interface ThemeAlias { [alias: string]: string; } -export function themeAlias(themePath: string): Alias { +export function themeAlias(themePath: string): ThemeAlias { if (!fs.pathExistsSync(themePath)) { return {}; } @@ -23,7 +23,7 @@ export function themeAlias(themePath: string): Alias { cwd: themePath, }); - const alias = {}; + const alias: ThemeAlias = {}; themeComponentFiles.forEach(relativeSource => { const filePath = path.join(themePath, relativeSource); const fileName = fileToPath(relativeSource); diff --git a/packages/docusaurus/src/server/themes/index.ts b/packages/docusaurus/src/server/themes/index.ts index 553ec1cfb2..5b7f081386 100644 --- a/packages/docusaurus/src/server/themes/index.ts +++ b/packages/docusaurus/src/server/themes/index.ts @@ -5,11 +5,11 @@ * LICENSE file in the root directory of this source tree. */ -import {themeAlias, Alias} from './alias'; +import {themeAlias, ThemeAlias} from './alias'; -export {Alias} from './alias'; +export {ThemeAlias} from './alias'; -export function loadThemeAlias(themePaths: string[]): Alias { +export function loadThemeAlias(themePaths: string[]): ThemeAlias { return themePaths.reduce( (alias, themePath) => ({ ...alias,