@docusaurus/core 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/docusaurus.mjs +10 -5
- package/lib/client/BrokenLinksContext.js +2 -2
- package/lib/client/exports/Link.js +10 -2
- package/lib/client/{serverRenderer.d.ts → renderToHtml.d.ts} +1 -1
- package/lib/client/{serverRenderer.js → renderToHtml.js} +1 -1
- package/lib/client/serverEntry.d.ts +3 -4
- package/lib/client/serverEntry.js +12 -113
- package/lib/client/theme-fallback/Error/index.js +22 -8
- package/lib/commands/build.d.ts +3 -3
- package/lib/commands/build.js +133 -112
- package/lib/commands/deploy.d.ts +2 -2
- package/lib/commands/deploy.js +3 -3
- package/lib/commands/external.js +2 -2
- package/lib/commands/serve.d.ts +2 -2
- package/lib/commands/serve.js +4 -4
- package/lib/commands/{start.d.ts → start/start.d.ts} +3 -3
- package/lib/commands/start/start.js +47 -0
- package/lib/commands/start/utils.d.ts +31 -0
- package/lib/commands/start/utils.js +87 -0
- package/lib/commands/start/watcher.d.ts +42 -0
- package/lib/commands/start/watcher.js +78 -0
- package/lib/commands/start/webpack.d.ts +15 -0
- package/lib/commands/start/webpack.js +133 -0
- package/lib/commands/swizzle/common.d.ts +1 -0
- package/lib/commands/swizzle/common.js +1 -0
- package/lib/commands/swizzle/context.js +2 -2
- package/lib/commands/swizzle/index.js +32 -3
- package/lib/commands/writeHeadingIds.js +2 -2
- package/lib/commands/writeTranslations.d.ts +2 -2
- package/lib/commands/writeTranslations.js +3 -3
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/server/brokenLinks.js +126 -39
- package/lib/server/clientModules.d.ts +1 -1
- package/lib/server/clientModules.js +3 -3
- package/lib/server/codegen/codegen.d.ts +20 -0
- package/lib/server/codegen/codegen.js +65 -0
- package/lib/server/codegen/codegenRoutes.d.ts +49 -0
- package/lib/server/codegen/codegenRoutes.js +190 -0
- package/lib/server/configValidation.js +6 -4
- package/lib/server/getHostPort.js +4 -1
- package/lib/server/i18n.d.ts +2 -2
- package/lib/server/i18n.js +20 -2
- package/lib/server/plugins/actions.d.ts +19 -0
- package/lib/server/plugins/actions.js +62 -0
- package/lib/server/plugins/init.js +3 -3
- package/lib/server/plugins/plugins.d.ts +21 -0
- package/lib/server/plugins/plugins.js +188 -0
- package/lib/server/plugins/pluginsUtils.d.ts +16 -0
- package/lib/server/plugins/pluginsUtils.js +75 -0
- package/lib/server/plugins/routeConfig.d.ts +1 -1
- package/lib/server/plugins/routeConfig.js +4 -4
- package/lib/server/plugins/synthetic.d.ts +3 -3
- package/lib/server/plugins/synthetic.js +0 -2
- package/lib/server/routes.d.ts +3 -45
- package/lib/server/routes.js +21 -165
- package/lib/server/{index.d.ts → site.d.ts} +12 -5
- package/lib/server/site.js +164 -0
- package/lib/server/siteMetadata.d.ts +5 -4
- package/lib/server/siteMetadata.js +14 -10
- package/lib/server/translations/translations.d.ts +9 -2
- package/lib/server/translations/translations.js +21 -4
- package/lib/server/utils.d.ts +0 -2
- package/lib/server/utils.js +1 -9
- package/lib/ssg.d.ts +31 -0
- package/lib/ssg.js +167 -0
- package/lib/templates/templates.d.ts +28 -0
- package/lib/templates/templates.js +63 -0
- package/lib/utils.d.ts +9 -0
- package/lib/utils.js +78 -0
- package/lib/webpack/base.d.ts +5 -1
- package/lib/webpack/base.js +4 -6
- package/lib/webpack/client.d.ts +15 -1
- package/lib/webpack/client.js +78 -23
- package/lib/webpack/minification.d.ts +8 -0
- package/lib/webpack/minification.js +97 -0
- package/lib/webpack/server.d.ts +5 -3
- package/lib/webpack/server.js +41 -50
- package/lib/webpack/utils.d.ts +13 -4
- package/lib/webpack/utils.js +27 -83
- package/package.json +13 -11
- package/lib/commands/start.js +0 -212
- package/lib/server/index.js +0 -154
- package/lib/server/plugins/index.d.ts +0 -18
- package/lib/server/plugins/index.js +0 -106
- /package/lib/{webpack/templates/index.html.template.ejs → templates/dev.html.template.ejs} +0 -0
- /package/lib/{webpack/templates → templates}/ssr.html.template.d.ts +0 -0
- /package/lib/{webpack/templates → templates}/ssr.html.template.js +0 -0
|
@@ -40,7 +40,10 @@ function getProcessForPort(port) {
|
|
|
40
40
|
*/
|
|
41
41
|
async function choosePort(host, defaultPort) {
|
|
42
42
|
try {
|
|
43
|
-
const port = await (0, detect_port_1.default)({
|
|
43
|
+
const port = await (0, detect_port_1.default)({
|
|
44
|
+
port: defaultPort,
|
|
45
|
+
...(host !== 'localhost' && { hostname: host }),
|
|
46
|
+
});
|
|
44
47
|
if (port === defaultPort) {
|
|
45
48
|
return port;
|
|
46
49
|
}
|
package/lib/server/i18n.d.ts
CHANGED
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { I18n, DocusaurusConfig, I18nLocaleConfig } from '@docusaurus/types';
|
|
8
|
-
import type {
|
|
8
|
+
import type { LoadContextParams } from './site';
|
|
9
9
|
export declare function getDefaultLocaleConfig(locale: string): I18nLocaleConfig;
|
|
10
|
-
export declare function loadI18n(config: DocusaurusConfig, options: Pick<
|
|
10
|
+
export declare function loadI18n(config: DocusaurusConfig, options: Pick<LoadContextParams, 'locale'>): Promise<I18n>;
|
package/lib/server/i18n.js
CHANGED
|
@@ -14,13 +14,31 @@ function getDefaultLocaleLabel(locale) {
|
|
|
14
14
|
const languageName = new Intl.DisplayNames(locale, { type: 'language' }).of(locale);
|
|
15
15
|
return (languageName.charAt(0).toLocaleUpperCase(locale) + languageName.substring(1));
|
|
16
16
|
}
|
|
17
|
+
function getDefaultCalendar(localeStr) {
|
|
18
|
+
const locale = new Intl.Locale(localeStr);
|
|
19
|
+
// If the locale name includes -u-ca-xxx the calendar will be defined
|
|
20
|
+
if (locale.calendar) {
|
|
21
|
+
return locale.calendar;
|
|
22
|
+
}
|
|
23
|
+
// Not well-supported but server code can infer a calendar from the locale
|
|
24
|
+
// See https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getCalendars
|
|
25
|
+
// See https://caniuse.com/mdn-javascript_builtins_intl_locale_getcalendars
|
|
26
|
+
const calendars =
|
|
27
|
+
// @ts-expect-error: new std method (Bun/JSC/WebKit)
|
|
28
|
+
locale.getCalendars?.() ??
|
|
29
|
+
// @ts-expect-error: non-std attribute (V8/Chromium/Node)
|
|
30
|
+
locale.calendars;
|
|
31
|
+
if (calendars instanceof Array && calendars[0]) {
|
|
32
|
+
return calendars[0];
|
|
33
|
+
}
|
|
34
|
+
return 'gregory';
|
|
35
|
+
}
|
|
17
36
|
function getDefaultLocaleConfig(locale) {
|
|
18
37
|
return {
|
|
19
38
|
label: getDefaultLocaleLabel(locale),
|
|
20
39
|
direction: (0, rtl_detect_1.getLangDir)(locale),
|
|
21
40
|
htmlLang: locale,
|
|
22
|
-
|
|
23
|
-
calendar: new Intl.Locale(locale).calendar ?? 'gregory',
|
|
41
|
+
calendar: getDefaultCalendar(locale),
|
|
24
42
|
path: locale,
|
|
25
43
|
};
|
|
26
44
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { InitializedPlugin, PluginContentLoadedActions, RouteConfig } from '@docusaurus/types';
|
|
8
|
+
type PluginActionUtils = {
|
|
9
|
+
getRoutes: () => RouteConfig[];
|
|
10
|
+
getGlobalData: () => unknown;
|
|
11
|
+
getActions: () => PluginContentLoadedActions;
|
|
12
|
+
};
|
|
13
|
+
export declare function createPluginActionsUtils({ plugin, generatedFilesDir, baseUrl, trailingSlash, }: {
|
|
14
|
+
plugin: InitializedPlugin;
|
|
15
|
+
generatedFilesDir: string;
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
trailingSlash: boolean | undefined;
|
|
18
|
+
}): Promise<PluginActionUtils>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createPluginActionsUtils = void 0;
|
|
10
|
+
const tslib_1 = require("tslib");
|
|
11
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
|
+
const utils_1 = require("@docusaurus/utils");
|
|
13
|
+
const routeConfig_1 = require("./routeConfig");
|
|
14
|
+
// TODO refactor historical action system and make this side-effect-free
|
|
15
|
+
// If the function were pure, we could more easily compare previous/next values
|
|
16
|
+
// on site reloads, and bail-out of the reload process earlier
|
|
17
|
+
// Particularly, createData() modules should rather be declarative
|
|
18
|
+
async function createPluginActionsUtils({ plugin, generatedFilesDir, baseUrl, trailingSlash, }) {
|
|
19
|
+
const pluginId = plugin.options.id;
|
|
20
|
+
// Plugins data files are namespaced by pluginName/pluginId
|
|
21
|
+
const dataDir = path_1.default.join(generatedFilesDir, plugin.name, pluginId);
|
|
22
|
+
const pluginRouteContext = {
|
|
23
|
+
name: plugin.name,
|
|
24
|
+
id: pluginId,
|
|
25
|
+
};
|
|
26
|
+
const pluginRouteContextModulePath = path_1.default.join(dataDir, `${(0, utils_1.docuHash)('pluginRouteContextModule')}.json`);
|
|
27
|
+
// TODO not ideal place to generate that file
|
|
28
|
+
await (0, utils_1.generate)('/', pluginRouteContextModulePath, JSON.stringify(pluginRouteContext, null, 2));
|
|
29
|
+
const routes = [];
|
|
30
|
+
let globalData;
|
|
31
|
+
const actions = {
|
|
32
|
+
addRoute(initialRouteConfig) {
|
|
33
|
+
// Trailing slash behavior is handled generically for all plugins
|
|
34
|
+
const finalRouteConfig = (0, routeConfig_1.applyRouteTrailingSlash)(initialRouteConfig, {
|
|
35
|
+
baseUrl,
|
|
36
|
+
trailingSlash,
|
|
37
|
+
});
|
|
38
|
+
routes.push({
|
|
39
|
+
...finalRouteConfig,
|
|
40
|
+
context: {
|
|
41
|
+
...(finalRouteConfig.context && { data: finalRouteConfig.context }),
|
|
42
|
+
plugin: pluginRouteContextModulePath,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
async createData(name, data) {
|
|
47
|
+
const modulePath = path_1.default.join(dataDir, name);
|
|
48
|
+
await (0, utils_1.generate)(dataDir, name, data);
|
|
49
|
+
return modulePath;
|
|
50
|
+
},
|
|
51
|
+
setGlobalData(data) {
|
|
52
|
+
globalData = data;
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
// Some variables are mutable, so we expose a getter instead of the value
|
|
57
|
+
getRoutes: () => routes,
|
|
58
|
+
getGlobalData: () => globalData,
|
|
59
|
+
getActions: () => actions,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
exports.createPluginActionsUtils = createPluginActionsUtils;
|
|
@@ -40,10 +40,10 @@ async function initPlugins(context) {
|
|
|
40
40
|
// we are using `require.resolve` on those module names.
|
|
41
41
|
const pluginRequire = (0, module_1.createRequire)(context.siteConfigPath);
|
|
42
42
|
const pluginConfigs = await (0, configs_1.loadPluginConfigs)(context);
|
|
43
|
-
async function
|
|
43
|
+
async function doLoadPluginVersion(normalizedPluginConfig) {
|
|
44
44
|
if (normalizedPluginConfig.pluginModule?.path) {
|
|
45
45
|
const pluginPath = pluginRequire.resolve(normalizedPluginConfig.pluginModule.path);
|
|
46
|
-
return (0, siteMetadata_1.
|
|
46
|
+
return (0, siteMetadata_1.loadPluginVersion)(pluginPath, context.siteDir);
|
|
47
47
|
}
|
|
48
48
|
return { type: 'local' };
|
|
49
49
|
}
|
|
@@ -73,7 +73,7 @@ async function initPlugins(context) {
|
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
75
|
async function initializePlugin(normalizedPluginConfig) {
|
|
76
|
-
const pluginVersion = await
|
|
76
|
+
const pluginVersion = await doLoadPluginVersion(normalizedPluginConfig);
|
|
77
77
|
const pluginOptions = doValidatePluginOptions(normalizedPluginConfig);
|
|
78
78
|
// Side-effect: merge the normalized theme config in the original one
|
|
79
79
|
context.siteConfig.themeConfig = {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { LoadContext, RouteConfig, GlobalData, PluginIdentifier, LoadedPlugin } from '@docusaurus/types';
|
|
8
|
+
export type LoadPluginsResult = {
|
|
9
|
+
plugins: LoadedPlugin[];
|
|
10
|
+
routes: RouteConfig[];
|
|
11
|
+
globalData: GlobalData;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Initializes the plugins and run their lifecycle functions.
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadPlugins(context: LoadContext): Promise<LoadPluginsResult>;
|
|
17
|
+
export declare function reloadPlugin({ pluginIdentifier, plugins: previousPlugins, context, }: {
|
|
18
|
+
pluginIdentifier: PluginIdentifier;
|
|
19
|
+
plugins: LoadedPlugin[];
|
|
20
|
+
context: LoadContext;
|
|
21
|
+
}): Promise<LoadPluginsResult>;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.reloadPlugin = exports.loadPlugins = void 0;
|
|
10
|
+
const init_1 = require("./init");
|
|
11
|
+
const synthetic_1 = require("./synthetic");
|
|
12
|
+
const translations_1 = require("../translations/translations");
|
|
13
|
+
const routeConfig_1 = require("./routeConfig");
|
|
14
|
+
const utils_1 = require("../../utils");
|
|
15
|
+
const actions_1 = require("./actions");
|
|
16
|
+
const pluginsUtils_1 = require("./pluginsUtils");
|
|
17
|
+
async function translatePluginContent({ plugin, content, context, }) {
|
|
18
|
+
const rawTranslationFiles = (await plugin.getTranslationFiles?.({ content })) ?? [];
|
|
19
|
+
const translationFiles = await Promise.all(rawTranslationFiles.map((translationFile) => (0, translations_1.localizePluginTranslationFile)({
|
|
20
|
+
localizationDir: context.localizationDir,
|
|
21
|
+
translationFile,
|
|
22
|
+
plugin,
|
|
23
|
+
})));
|
|
24
|
+
const translatedContent = plugin.translateContent?.({ content, translationFiles }) ?? content;
|
|
25
|
+
const translatedThemeConfigSlice = plugin.translateThemeConfig?.({
|
|
26
|
+
themeConfig: context.siteConfig.themeConfig,
|
|
27
|
+
translationFiles,
|
|
28
|
+
});
|
|
29
|
+
// TODO dangerous legacy, need to be refactored!
|
|
30
|
+
// Side-effect to merge theme config translations. A plugin should only
|
|
31
|
+
// translate its own slice of theme config and should make no assumptions
|
|
32
|
+
// about other plugins' keys, so this is safe to run in parallel.
|
|
33
|
+
Object.assign(context.siteConfig.themeConfig, translatedThemeConfigSlice);
|
|
34
|
+
return translatedContent;
|
|
35
|
+
}
|
|
36
|
+
async function executePluginContentLoading({ plugin, context, }) {
|
|
37
|
+
return utils_1.PerfLogger.async(`Load ${(0, pluginsUtils_1.formatPluginName)(plugin)}`, async () => {
|
|
38
|
+
let content = await utils_1.PerfLogger.async('loadContent()', () => plugin.loadContent?.());
|
|
39
|
+
content = await utils_1.PerfLogger.async('translatePluginContent()', () => translatePluginContent({
|
|
40
|
+
plugin,
|
|
41
|
+
content,
|
|
42
|
+
context,
|
|
43
|
+
}));
|
|
44
|
+
const defaultCodeTranslations = (await utils_1.PerfLogger.async('getDefaultCodeTranslationMessages()', () => plugin.getDefaultCodeTranslationMessages?.())) ?? {};
|
|
45
|
+
if (!plugin.contentLoaded) {
|
|
46
|
+
return {
|
|
47
|
+
...plugin,
|
|
48
|
+
content,
|
|
49
|
+
defaultCodeTranslations,
|
|
50
|
+
routes: [],
|
|
51
|
+
globalData: undefined,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const pluginActionsUtils = await (0, actions_1.createPluginActionsUtils)({
|
|
55
|
+
plugin,
|
|
56
|
+
generatedFilesDir: context.generatedFilesDir,
|
|
57
|
+
baseUrl: context.siteConfig.baseUrl,
|
|
58
|
+
trailingSlash: context.siteConfig.trailingSlash,
|
|
59
|
+
});
|
|
60
|
+
await utils_1.PerfLogger.async('contentLoaded()', () =>
|
|
61
|
+
// @ts-expect-error: should autofix with TS 5.4
|
|
62
|
+
plugin.contentLoaded({
|
|
63
|
+
content,
|
|
64
|
+
actions: pluginActionsUtils.getActions(),
|
|
65
|
+
}));
|
|
66
|
+
return {
|
|
67
|
+
...plugin,
|
|
68
|
+
content,
|
|
69
|
+
defaultCodeTranslations,
|
|
70
|
+
routes: pluginActionsUtils.getRoutes(),
|
|
71
|
+
globalData: pluginActionsUtils.getGlobalData(),
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async function executeAllPluginsContentLoading({ plugins, context, }) {
|
|
76
|
+
return utils_1.PerfLogger.async(`Load plugins content`, () => {
|
|
77
|
+
return Promise.all(plugins.map((plugin) => executePluginContentLoading({ plugin, context })));
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async function executePluginAllContentLoaded({ plugin, context, allContent, }) {
|
|
81
|
+
return utils_1.PerfLogger.async(`allContentLoaded() - ${(0, pluginsUtils_1.formatPluginName)(plugin)}`, async () => {
|
|
82
|
+
if (!plugin.allContentLoaded) {
|
|
83
|
+
return { routes: [], globalData: undefined };
|
|
84
|
+
}
|
|
85
|
+
const pluginActionsUtils = await (0, actions_1.createPluginActionsUtils)({
|
|
86
|
+
plugin,
|
|
87
|
+
generatedFilesDir: context.generatedFilesDir,
|
|
88
|
+
baseUrl: context.siteConfig.baseUrl,
|
|
89
|
+
trailingSlash: context.siteConfig.trailingSlash,
|
|
90
|
+
});
|
|
91
|
+
await plugin.allContentLoaded({
|
|
92
|
+
allContent,
|
|
93
|
+
actions: pluginActionsUtils.getActions(),
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
routes: pluginActionsUtils.getRoutes(),
|
|
97
|
+
globalData: pluginActionsUtils.getGlobalData(),
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async function executeAllPluginsAllContentLoaded({ plugins, context, }) {
|
|
102
|
+
return utils_1.PerfLogger.async(`allContentLoaded()`, async () => {
|
|
103
|
+
const allContent = (0, pluginsUtils_1.aggregateAllContent)(plugins);
|
|
104
|
+
const routes = [];
|
|
105
|
+
const globalData = {};
|
|
106
|
+
await Promise.all(plugins.map(async (plugin) => {
|
|
107
|
+
var _a;
|
|
108
|
+
const { routes: pluginRoutes, globalData: pluginGlobalData } = await executePluginAllContentLoaded({
|
|
109
|
+
plugin,
|
|
110
|
+
context,
|
|
111
|
+
allContent,
|
|
112
|
+
});
|
|
113
|
+
routes.push(...pluginRoutes);
|
|
114
|
+
if (pluginGlobalData !== undefined) {
|
|
115
|
+
globalData[_a = plugin.name] ?? (globalData[_a] = {});
|
|
116
|
+
globalData[plugin.name][plugin.options.id] = pluginGlobalData;
|
|
117
|
+
}
|
|
118
|
+
}));
|
|
119
|
+
return { routes, globalData };
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// This merges plugins routes and global data created from both lifecycles:
|
|
123
|
+
// - contentLoaded()
|
|
124
|
+
// - allContentLoaded()
|
|
125
|
+
function mergeResults({ plugins, allContentLoadedResult, }) {
|
|
126
|
+
const routes = [
|
|
127
|
+
...(0, pluginsUtils_1.aggregateRoutes)(plugins),
|
|
128
|
+
...allContentLoadedResult.routes,
|
|
129
|
+
];
|
|
130
|
+
(0, routeConfig_1.sortRoutes)(routes);
|
|
131
|
+
const globalData = (0, pluginsUtils_1.mergeGlobalData)((0, pluginsUtils_1.aggregateGlobalData)(plugins), allContentLoadedResult.globalData);
|
|
132
|
+
return { routes, globalData };
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Initializes the plugins and run their lifecycle functions.
|
|
136
|
+
*/
|
|
137
|
+
async function loadPlugins(context) {
|
|
138
|
+
return utils_1.PerfLogger.async('Load plugins', async () => {
|
|
139
|
+
const initializedPlugins = await utils_1.PerfLogger.async('Init plugins', () => (0, init_1.initPlugins)(context));
|
|
140
|
+
// TODO probably not the ideal place to hardcode those plugins
|
|
141
|
+
initializedPlugins.push((0, synthetic_1.createBootstrapPlugin)(context), (0, synthetic_1.createMDXFallbackPlugin)(context));
|
|
142
|
+
const plugins = await executeAllPluginsContentLoading({
|
|
143
|
+
plugins: initializedPlugins,
|
|
144
|
+
context,
|
|
145
|
+
});
|
|
146
|
+
const allContentLoadedResult = await executeAllPluginsAllContentLoaded({
|
|
147
|
+
plugins,
|
|
148
|
+
context,
|
|
149
|
+
});
|
|
150
|
+
const { routes, globalData } = mergeResults({
|
|
151
|
+
plugins,
|
|
152
|
+
allContentLoadedResult,
|
|
153
|
+
});
|
|
154
|
+
return { plugins, routes, globalData };
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
exports.loadPlugins = loadPlugins;
|
|
158
|
+
async function reloadPlugin({ pluginIdentifier, plugins: previousPlugins, context, }) {
|
|
159
|
+
return utils_1.PerfLogger.async(`Reload plugin ${(0, pluginsUtils_1.formatPluginName)(pluginIdentifier)}`, async () => {
|
|
160
|
+
const previousPlugin = (0, pluginsUtils_1.getPluginByIdentifier)({
|
|
161
|
+
plugins: previousPlugins,
|
|
162
|
+
pluginIdentifier,
|
|
163
|
+
});
|
|
164
|
+
const plugin = await executePluginContentLoading({
|
|
165
|
+
plugin: previousPlugin,
|
|
166
|
+
context,
|
|
167
|
+
});
|
|
168
|
+
/*
|
|
169
|
+
// TODO Docusaurus v4 - upgrade to Node 20, use array.with()
|
|
170
|
+
const plugins = previousPlugins.with(
|
|
171
|
+
previousPlugins.indexOf(previousPlugin),
|
|
172
|
+
plugin,
|
|
173
|
+
);
|
|
174
|
+
*/
|
|
175
|
+
const plugins = [...previousPlugins];
|
|
176
|
+
plugins[previousPlugins.indexOf(previousPlugin)] = plugin;
|
|
177
|
+
const allContentLoadedResult = await executeAllPluginsAllContentLoaded({
|
|
178
|
+
plugins,
|
|
179
|
+
context,
|
|
180
|
+
});
|
|
181
|
+
const { routes, globalData } = mergeResults({
|
|
182
|
+
plugins,
|
|
183
|
+
allContentLoadedResult,
|
|
184
|
+
});
|
|
185
|
+
return { plugins, routes, globalData };
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
exports.reloadPlugin = reloadPlugin;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { AllContent, GlobalData, InitializedPlugin, LoadedPlugin, PluginIdentifier, RouteConfig } from '@docusaurus/types';
|
|
8
|
+
export declare function getPluginByIdentifier<P extends InitializedPlugin>({ plugins, pluginIdentifier, }: {
|
|
9
|
+
pluginIdentifier: PluginIdentifier;
|
|
10
|
+
plugins: P[];
|
|
11
|
+
}): P;
|
|
12
|
+
export declare function aggregateAllContent(loadedPlugins: LoadedPlugin[]): AllContent;
|
|
13
|
+
export declare function aggregateRoutes(loadedPlugins: LoadedPlugin[]): RouteConfig[];
|
|
14
|
+
export declare function aggregateGlobalData(loadedPlugins: LoadedPlugin[]): GlobalData;
|
|
15
|
+
export declare function mergeGlobalData(...globalDataList: GlobalData[]): GlobalData;
|
|
16
|
+
export declare function formatPluginName(plugin: InitializedPlugin | PluginIdentifier): string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.formatPluginName = exports.mergeGlobalData = exports.aggregateGlobalData = exports.aggregateRoutes = exports.aggregateAllContent = exports.getPluginByIdentifier = void 0;
|
|
10
|
+
const tslib_1 = require("tslib");
|
|
11
|
+
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
12
|
+
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
13
|
+
function getPluginByIdentifier({ plugins, pluginIdentifier, }) {
|
|
14
|
+
const plugin = plugins.find((p) => p.name === pluginIdentifier.name && p.options.id === pluginIdentifier.id);
|
|
15
|
+
if (!plugin) {
|
|
16
|
+
throw new Error(logger_1.default.interpolate `Plugin not found for identifier ${formatPluginName(pluginIdentifier)}`);
|
|
17
|
+
}
|
|
18
|
+
return plugin;
|
|
19
|
+
}
|
|
20
|
+
exports.getPluginByIdentifier = getPluginByIdentifier;
|
|
21
|
+
function aggregateAllContent(loadedPlugins) {
|
|
22
|
+
return lodash_1.default.chain(loadedPlugins)
|
|
23
|
+
.groupBy((item) => item.name)
|
|
24
|
+
.mapValues((nameItems) => lodash_1.default.chain(nameItems)
|
|
25
|
+
.groupBy((item) => item.options.id)
|
|
26
|
+
.mapValues((idItems) => idItems[0].content)
|
|
27
|
+
.value())
|
|
28
|
+
.value();
|
|
29
|
+
}
|
|
30
|
+
exports.aggregateAllContent = aggregateAllContent;
|
|
31
|
+
function aggregateRoutes(loadedPlugins) {
|
|
32
|
+
return loadedPlugins.flatMap((p) => p.routes);
|
|
33
|
+
}
|
|
34
|
+
exports.aggregateRoutes = aggregateRoutes;
|
|
35
|
+
function aggregateGlobalData(loadedPlugins) {
|
|
36
|
+
const globalData = {};
|
|
37
|
+
loadedPlugins.forEach((plugin) => {
|
|
38
|
+
var _a;
|
|
39
|
+
if (plugin.globalData !== undefined) {
|
|
40
|
+
globalData[_a = plugin.name] ?? (globalData[_a] = {});
|
|
41
|
+
globalData[plugin.name][plugin.options.id] = plugin.globalData;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
return globalData;
|
|
45
|
+
}
|
|
46
|
+
exports.aggregateGlobalData = aggregateGlobalData;
|
|
47
|
+
function mergeGlobalData(...globalDataList) {
|
|
48
|
+
const result = {};
|
|
49
|
+
const allPluginIdentifiers = globalDataList.flatMap((gd) => Object.keys(gd).flatMap((name) => Object.keys(gd[name]).map((id) => ({ name, id }))));
|
|
50
|
+
allPluginIdentifiers.forEach(({ name, id }) => {
|
|
51
|
+
const allData = globalDataList
|
|
52
|
+
.map((gd) => gd?.[name]?.[id])
|
|
53
|
+
.filter((d) => typeof d !== 'undefined');
|
|
54
|
+
const mergedData = allData.length === 1 ? allData[0] : Object.assign({}, ...allData);
|
|
55
|
+
result[name] ?? (result[name] = {});
|
|
56
|
+
result[name][id] = mergedData;
|
|
57
|
+
});
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
exports.mergeGlobalData = mergeGlobalData;
|
|
61
|
+
// This is primarily useful for colored logging purpose
|
|
62
|
+
// Do not rely on this for logic
|
|
63
|
+
function formatPluginName(plugin) {
|
|
64
|
+
let formattedName = plugin.name;
|
|
65
|
+
// Hacky way to reduce string size for logging purpose
|
|
66
|
+
formattedName = formattedName.replace('docusaurus-plugin-content-', '');
|
|
67
|
+
formattedName = formattedName.replace('docusaurus-plugin-', '');
|
|
68
|
+
formattedName = formattedName.replace('docusaurus-theme-', '');
|
|
69
|
+
formattedName = formattedName.replace('-plugin', '');
|
|
70
|
+
formattedName = logger_1.default.name(formattedName);
|
|
71
|
+
const id = 'id' in plugin ? plugin.id : plugin.options.id;
|
|
72
|
+
const formattedId = logger_1.default.subdue(id);
|
|
73
|
+
return `${formattedName}@${formattedId}`;
|
|
74
|
+
}
|
|
75
|
+
exports.formatPluginName = formatPluginName;
|
|
@@ -8,4 +8,4 @@ import { type ApplyTrailingSlashParams } from '@docusaurus/utils-common';
|
|
|
8
8
|
import type { RouteConfig } from '@docusaurus/types';
|
|
9
9
|
/** Recursively applies trailing slash config to all nested routes. */
|
|
10
10
|
export declare function applyRouteTrailingSlash(route: RouteConfig, params: ApplyTrailingSlashParams): RouteConfig;
|
|
11
|
-
export declare function
|
|
11
|
+
export declare function sortRoutes(routeConfigs: RouteConfig[], baseUrl?: string): void;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.
|
|
9
|
+
exports.sortRoutes = exports.applyRouteTrailingSlash = void 0;
|
|
10
10
|
const utils_common_1 = require("@docusaurus/utils-common");
|
|
11
11
|
/** Recursively applies trailing slash config to all nested routes. */
|
|
12
12
|
function applyRouteTrailingSlash(route, params) {
|
|
@@ -19,7 +19,7 @@ function applyRouteTrailingSlash(route, params) {
|
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
exports.applyRouteTrailingSlash = applyRouteTrailingSlash;
|
|
22
|
-
function
|
|
22
|
+
function sortRoutes(routeConfigs, baseUrl = '/') {
|
|
23
23
|
// Sort the route config. This ensures that route with nested
|
|
24
24
|
// routes is always placed last.
|
|
25
25
|
routeConfigs.sort((a, b) => {
|
|
@@ -49,8 +49,8 @@ function sortConfig(routeConfigs, baseUrl = '/') {
|
|
|
49
49
|
});
|
|
50
50
|
routeConfigs.forEach((routeConfig) => {
|
|
51
51
|
if (routeConfig.routes) {
|
|
52
|
-
|
|
52
|
+
sortRoutes(routeConfig.routes, baseUrl);
|
|
53
53
|
}
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
-
exports.
|
|
56
|
+
exports.sortRoutes = sortRoutes;
|
|
@@ -4,17 +4,17 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
7
|
+
import type { LoadContext, InitializedPlugin } from '@docusaurus/types';
|
|
8
8
|
/**
|
|
9
9
|
* Make a synthetic plugin to:
|
|
10
10
|
* - Inject site client modules
|
|
11
11
|
* - Inject scripts/stylesheets
|
|
12
12
|
*/
|
|
13
|
-
export declare function createBootstrapPlugin({ siteDir, siteConfig, }: LoadContext):
|
|
13
|
+
export declare function createBootstrapPlugin({ siteDir, siteConfig, }: LoadContext): InitializedPlugin;
|
|
14
14
|
/**
|
|
15
15
|
* Configure Webpack fallback mdx loader for md/mdx files out of content-plugin
|
|
16
16
|
* folders. Adds a "fallback" mdx loader for mdx files that are not processed by
|
|
17
17
|
* content plugins. This allows to do things such as importing repo/README.md as
|
|
18
18
|
* a partial from another doc. Not ideal solution, but good enough for now
|
|
19
19
|
*/
|
|
20
|
-
export declare function createMDXFallbackPlugin({ siteDir, siteConfig, }: LoadContext):
|
|
20
|
+
export declare function createMDXFallbackPlugin({ siteDir, siteConfig, }: LoadContext): InitializedPlugin;
|
|
@@ -18,7 +18,6 @@ function createBootstrapPlugin({ siteDir, siteConfig, }) {
|
|
|
18
18
|
const { stylesheets, scripts, headTags, clientModules: siteConfigClientModules, } = siteConfig;
|
|
19
19
|
return {
|
|
20
20
|
name: 'docusaurus-bootstrap-plugin',
|
|
21
|
-
content: null,
|
|
22
21
|
options: {
|
|
23
22
|
id: 'default',
|
|
24
23
|
},
|
|
@@ -61,7 +60,6 @@ exports.createBootstrapPlugin = createBootstrapPlugin;
|
|
|
61
60
|
function createMDXFallbackPlugin({ siteDir, siteConfig, }) {
|
|
62
61
|
return {
|
|
63
62
|
name: 'docusaurus-mdx-fallback-plugin',
|
|
64
|
-
content: null,
|
|
65
63
|
options: {
|
|
66
64
|
id: 'default',
|
|
67
65
|
},
|
package/lib/server/routes.d.ts
CHANGED
|
@@ -4,48 +4,6 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import type { RouteConfig,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
routesConfig: string;
|
|
11
|
-
/** @see {ChunkNames} */
|
|
12
|
-
routesChunkNames: RouteChunkNames;
|
|
13
|
-
/**
|
|
14
|
-
* A map from chunk name to module paths. Module paths would have backslash
|
|
15
|
-
* escaped already, so they can be directly printed.
|
|
16
|
-
*/
|
|
17
|
-
registry: {
|
|
18
|
-
[chunkName: string]: string;
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Collect all page paths for injecting it later in the plugin lifecycle.
|
|
22
|
-
* This is useful for plugins like sitemaps, redirects etc... Only collects
|
|
23
|
-
* "actual" pages, i.e. those without subroutes, because if a route has
|
|
24
|
-
* subroutes, it is probably a wrapper.
|
|
25
|
-
*/
|
|
26
|
-
routesPaths: string[];
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Generates a unique chunk name that can be used in the chunk registry.
|
|
30
|
-
*
|
|
31
|
-
* @param modulePath A path to generate chunk name from. The actual value has no
|
|
32
|
-
* semantic significance.
|
|
33
|
-
* @param prefix A prefix to append to the chunk name, to avoid name clash.
|
|
34
|
-
* @param preferredName Chunk names default to `modulePath`, and this can supply
|
|
35
|
-
* a more human-readable name.
|
|
36
|
-
* @param shortId When `true`, the chunk name would only be a hash without any
|
|
37
|
-
* other characters. Useful for bundle size. Defaults to `true` in production.
|
|
38
|
-
*/
|
|
39
|
-
export declare function genChunkName(modulePath: string, prefix?: string, preferredName?: string, shortId?: boolean): string;
|
|
40
|
-
export declare function handleDuplicateRoutes(pluginsRouteConfigs: RouteConfig[], onDuplicateRoutes: ReportingSeverity): void;
|
|
41
|
-
/**
|
|
42
|
-
* Routes are prepared into three temp files:
|
|
43
|
-
*
|
|
44
|
-
* - `routesConfig`, the route config passed to react-router. This file is kept
|
|
45
|
-
* minimal, because it can't be code-splitted.
|
|
46
|
-
* - `routesChunkNames`, a mapping from route paths (hashed) to code-splitted
|
|
47
|
-
* chunk names.
|
|
48
|
-
* - `registry`, a mapping from chunk names to options for react-loadable.
|
|
49
|
-
*/
|
|
50
|
-
export declare function loadRoutes(routeConfigs: RouteConfig[], baseUrl: string, onDuplicateRoutes: ReportingSeverity): LoadedRoutes;
|
|
51
|
-
export {};
|
|
7
|
+
import type { RouteConfig, ReportingSeverity } from '@docusaurus/types';
|
|
8
|
+
export declare function handleDuplicateRoutes(routes: RouteConfig[], onDuplicateRoutes: ReportingSeverity): void;
|
|
9
|
+
export declare function getRoutesPaths(routeConfigs: RouteConfig[], baseUrl: string): string[];
|