mirror of
https://github.com/facebook/docusaurus.git
synced 2025-12-28 20:52:48 +00:00
misc(v2): add more typing for server code (#1548)
* refactor(v2): add types to loading code * misc(v2): better typing * misc(v2): rename presets * misc(v2): further typing * fix typing for webpack config
This commit is contained in:
parent
5af8cd566e
commit
7115cfc743
|
|
@ -59,7 +59,7 @@ export async function start(
|
|||
};
|
||||
|
||||
const pluginPaths = _.compact(
|
||||
_.flatten(
|
||||
_.flatten<string | undefined>(
|
||||
plugins.map(plugin => plugin.getPathsToWatch && plugin.getPathsToWatch()),
|
||||
),
|
||||
).map(normalizeToSiteDir);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<any>[];
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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<T> {
|
||||
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<string>;
|
||||
}
|
||||
|
||||
export async function loadPlugins({
|
||||
pluginConfigs = [],
|
||||
pluginConfigs,
|
||||
context,
|
||||
}: {
|
||||
pluginConfigs: any[];
|
||||
pluginConfigs: PluginConfig[];
|
||||
context: LoadContext;
|
||||
}) {
|
||||
}): Promise<{
|
||||
plugins: Plugin<any>[];
|
||||
pluginsRouteConfigs: RouteConfig[];
|
||||
}> {
|
||||
// 1. Plugin Lifecycle - Initialization/Constructor
|
||||
const plugins = pluginConfigs.map(({module, options}) => {
|
||||
const plugins: Plugin<any>[] = 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,
|
||||
});
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -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<PluginConfig | undefined>(plugins)),
|
||||
themes: _.compact(_.flatten<PluginConfig | undefined>(themes)),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue