@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
package/lib/server/routes.js
CHANGED
|
@@ -6,115 +6,15 @@
|
|
|
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.getRoutesPaths = exports.handleDuplicateRoutes = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
|
-
const querystring_1 = tslib_1.__importDefault(require("querystring"));
|
|
12
|
-
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
13
11
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
14
12
|
const utils_1 = require("@docusaurus/utils");
|
|
15
|
-
|
|
16
|
-
/** Indents every line of `str` by one level. */
|
|
17
|
-
function indent(str) {
|
|
18
|
-
return ` ${str.replace(/\n/g, `\n `)}`;
|
|
19
|
-
}
|
|
20
|
-
const chunkNameCache = new Map();
|
|
21
|
-
const chunkNameCount = new Map();
|
|
22
|
-
/**
|
|
23
|
-
* Generates a unique chunk name that can be used in the chunk registry.
|
|
24
|
-
*
|
|
25
|
-
* @param modulePath A path to generate chunk name from. The actual value has no
|
|
26
|
-
* semantic significance.
|
|
27
|
-
* @param prefix A prefix to append to the chunk name, to avoid name clash.
|
|
28
|
-
* @param preferredName Chunk names default to `modulePath`, and this can supply
|
|
29
|
-
* a more human-readable name.
|
|
30
|
-
* @param shortId When `true`, the chunk name would only be a hash without any
|
|
31
|
-
* other characters. Useful for bundle size. Defaults to `true` in production.
|
|
32
|
-
*/
|
|
33
|
-
function genChunkName(modulePath, prefix, preferredName, shortId = process.env.NODE_ENV === 'production') {
|
|
34
|
-
let chunkName = chunkNameCache.get(modulePath);
|
|
35
|
-
if (!chunkName) {
|
|
36
|
-
if (shortId) {
|
|
37
|
-
chunkName = (0, utils_1.simpleHash)(modulePath, 8);
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
let str = modulePath;
|
|
41
|
-
if (preferredName) {
|
|
42
|
-
const shortHash = (0, utils_1.simpleHash)(modulePath, 3);
|
|
43
|
-
str = `${preferredName}${shortHash}`;
|
|
44
|
-
}
|
|
45
|
-
const name = (0, utils_1.docuHash)(str);
|
|
46
|
-
chunkName = prefix ? `${prefix}---${name}` : name;
|
|
47
|
-
}
|
|
48
|
-
const seenCount = (chunkNameCount.get(chunkName) ?? 0) + 1;
|
|
49
|
-
if (seenCount > 1) {
|
|
50
|
-
chunkName += seenCount.toString(36);
|
|
51
|
-
}
|
|
52
|
-
chunkNameCache.set(modulePath, chunkName);
|
|
53
|
-
chunkNameCount.set(chunkName, seenCount);
|
|
54
|
-
}
|
|
55
|
-
return chunkName;
|
|
56
|
-
}
|
|
57
|
-
exports.genChunkName = genChunkName;
|
|
58
|
-
/**
|
|
59
|
-
* Takes a piece of route config, and serializes it into raw JS code. The shape
|
|
60
|
-
* is the same as react-router's `RouteConfig`. Formatting is similar to
|
|
61
|
-
* `JSON.stringify` but without all the quotes.
|
|
62
|
-
*/
|
|
63
|
-
function serializeRouteConfig({ routePath, routeHash, exact, subroutesCodeStrings, props, }) {
|
|
64
|
-
const parts = [
|
|
65
|
-
`path: '${routePath}'`,
|
|
66
|
-
`component: ComponentCreator('${routePath}', '${routeHash}')`,
|
|
67
|
-
];
|
|
68
|
-
if (exact) {
|
|
69
|
-
parts.push(`exact: true`);
|
|
70
|
-
}
|
|
71
|
-
if (subroutesCodeStrings) {
|
|
72
|
-
parts.push(`routes: [
|
|
73
|
-
${indent(subroutesCodeStrings.join(',\n'))}
|
|
74
|
-
]`);
|
|
75
|
-
}
|
|
76
|
-
Object.entries(props).forEach(([propName, propValue]) => {
|
|
77
|
-
const isIdentifier = /^[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*$/u.test(propName);
|
|
78
|
-
const key = isIdentifier ? propName : JSON.stringify(propName);
|
|
79
|
-
parts.push(`${key}: ${JSON.stringify(propValue)}`);
|
|
80
|
-
});
|
|
81
|
-
return `{
|
|
82
|
-
${indent(parts.join(',\n'))}
|
|
83
|
-
}`;
|
|
84
|
-
}
|
|
85
|
-
const isModule = (value) => typeof value === 'string' ||
|
|
86
|
-
(typeof value === 'object' &&
|
|
87
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
88
|
-
!!value?.__import);
|
|
89
|
-
/**
|
|
90
|
-
* Takes a {@link Module} (which is nothing more than a path plus some metadata
|
|
91
|
-
* like query) and returns the string path it represents.
|
|
92
|
-
*/
|
|
93
|
-
function getModulePath(target) {
|
|
94
|
-
if (typeof target === 'string') {
|
|
95
|
-
return target;
|
|
96
|
-
}
|
|
97
|
-
const queryStr = target.query ? `?${querystring_1.default.stringify(target.query)}` : '';
|
|
98
|
-
return `${target.path}${queryStr}`;
|
|
99
|
-
}
|
|
100
|
-
function genChunkNames(routeModule, prefix, name, res) {
|
|
101
|
-
if (isModule(routeModule)) {
|
|
102
|
-
// This is a leaf node, no need to recurse
|
|
103
|
-
const modulePath = getModulePath(routeModule);
|
|
104
|
-
const chunkName = genChunkName(modulePath, prefix, name);
|
|
105
|
-
res.registry[chunkName] = (0, utils_1.escapePath)(modulePath);
|
|
106
|
-
return chunkName;
|
|
107
|
-
}
|
|
108
|
-
if (Array.isArray(routeModule)) {
|
|
109
|
-
return routeModule.map((val, index) => genChunkNames(val, `${index}`, name, res));
|
|
110
|
-
}
|
|
111
|
-
return lodash_1.default.mapValues(routeModule, (v, key) => genChunkNames(v, key, name, res));
|
|
112
|
-
}
|
|
113
|
-
function handleDuplicateRoutes(pluginsRouteConfigs, onDuplicateRoutes) {
|
|
13
|
+
function handleDuplicateRoutes(routes, onDuplicateRoutes) {
|
|
114
14
|
if (onDuplicateRoutes === 'ignore') {
|
|
115
15
|
return;
|
|
116
16
|
}
|
|
117
|
-
const allRoutes = (0,
|
|
17
|
+
const allRoutes = (0, utils_1.flattenRoutes)(routes).map((routeConfig) => routeConfig.path);
|
|
118
18
|
const seenRoutes = new Set();
|
|
119
19
|
const duplicatePaths = allRoutes.filter((route) => {
|
|
120
20
|
if (seenRoutes.has(route)) {
|
|
@@ -130,68 +30,24 @@ This could lead to non-deterministic routing behavior.`;
|
|
|
130
30
|
}
|
|
131
31
|
exports.handleDuplicateRoutes = handleDuplicateRoutes;
|
|
132
32
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
res.routesPaths.push(routePath);
|
|
145
|
-
}
|
|
146
|
-
const routeHash = (0, utils_1.simpleHash)(JSON.stringify(routeConfig), 3);
|
|
147
|
-
res.routesChunkNames[`${routePath}-${routeHash}`] = {
|
|
148
|
-
// Avoid clash with a prop called "component"
|
|
149
|
-
...genChunkNames({ __comp: component }, 'component', component, res),
|
|
150
|
-
...(context &&
|
|
151
|
-
genChunkNames({ __context: context }, 'context', routePath, res)),
|
|
152
|
-
...genChunkNames(modules, 'module', routePath, res),
|
|
153
|
-
};
|
|
154
|
-
return serializeRouteConfig({
|
|
155
|
-
routePath: routePath.replace(/'/g, "\\'"),
|
|
156
|
-
routeHash,
|
|
157
|
-
subroutesCodeStrings: subroutes?.map((r) => genRouteCode(r, res)),
|
|
158
|
-
exact,
|
|
159
|
-
props,
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Routes are prepared into three temp files:
|
|
33
|
+
* Old stuff
|
|
34
|
+
* As far as I understand, this is what permits to SSG the 404.html file
|
|
35
|
+
* This is rendered through the catch-all ComponentCreator("*") route
|
|
36
|
+
* Note CDNs only understand the 404.html file by convention
|
|
37
|
+
* The extension probably permits to avoid emitting "/404/index.html"
|
|
38
|
+
*
|
|
39
|
+
* TODO we should probably deprecate/remove "postBuild({routesPaths})
|
|
40
|
+
* The 404 generation handling can be moved to the SSG code
|
|
41
|
+
* We only need getAllFinalRoutes() utils IMHO
|
|
42
|
+
* This would be a plugin lifecycle breaking change :/
|
|
43
|
+
* Although not many plugins probably use this
|
|
164
44
|
*
|
|
165
|
-
* - `routesConfig`, the route config passed to react-router. This file is kept
|
|
166
|
-
* minimal, because it can't be code-splitted.
|
|
167
|
-
* - `routesChunkNames`, a mapping from route paths (hashed) to code-splitted
|
|
168
|
-
* chunk names.
|
|
169
|
-
* - `registry`, a mapping from chunk names to options for react-loadable.
|
|
170
45
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
registry: {},
|
|
178
|
-
routesPaths: [(0, utils_1.normalizeUrl)([baseUrl, '404.html'])],
|
|
179
|
-
};
|
|
180
|
-
// `genRouteCode` would mutate `res`
|
|
181
|
-
const routeConfigSerialized = routeConfigs
|
|
182
|
-
.map((r) => genRouteCode(r, res))
|
|
183
|
-
.join(',\n');
|
|
184
|
-
res.routesConfig = `import React from 'react';
|
|
185
|
-
import ComponentCreator from '@docusaurus/ComponentCreator';
|
|
186
|
-
|
|
187
|
-
export default [
|
|
188
|
-
${indent(routeConfigSerialized)},
|
|
189
|
-
{
|
|
190
|
-
path: '*',
|
|
191
|
-
component: ComponentCreator('*'),
|
|
192
|
-
},
|
|
193
|
-
];
|
|
194
|
-
`;
|
|
195
|
-
return res;
|
|
46
|
+
const NotFoundRoutePath = '/404.html';
|
|
47
|
+
function getRoutesPaths(routeConfigs, baseUrl) {
|
|
48
|
+
return [
|
|
49
|
+
(0, utils_1.normalizeUrl)([baseUrl, NotFoundRoutePath]),
|
|
50
|
+
...(0, utils_1.flattenRoutes)(routeConfigs).map((r) => r.path),
|
|
51
|
+
];
|
|
196
52
|
}
|
|
197
|
-
exports.
|
|
53
|
+
exports.getRoutesPaths = getRoutesPaths;
|
|
@@ -4,8 +4,8 @@
|
|
|
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 { LoadContext, Props } from '@docusaurus/types';
|
|
8
|
-
export type
|
|
7
|
+
import type { LoadContext, Props, PluginIdentifier } from '@docusaurus/types';
|
|
8
|
+
export type LoadContextParams = {
|
|
9
9
|
/** Usually the CWD; can be overridden with command argument. */
|
|
10
10
|
siteDir: string;
|
|
11
11
|
/** Custom output directory. Can be customized with `--out-dir` option */
|
|
@@ -22,17 +22,24 @@ export type LoadContextOptions = {
|
|
|
22
22
|
*/
|
|
23
23
|
localizePath?: boolean;
|
|
24
24
|
};
|
|
25
|
+
export type LoadSiteParams = LoadContextParams;
|
|
26
|
+
export type Site = {
|
|
27
|
+
props: Props;
|
|
28
|
+
params: LoadSiteParams;
|
|
29
|
+
};
|
|
25
30
|
/**
|
|
26
|
-
* Loading context is the very first step in site building. Its
|
|
31
|
+
* Loading context is the very first step in site building. Its params are
|
|
27
32
|
* directly acquired from CLI options. It mainly loads `siteConfig` and the i18n
|
|
28
33
|
* context (which includes code translations). The `LoadContext` will be passed
|
|
29
34
|
* to plugin constructors.
|
|
30
35
|
*/
|
|
31
|
-
export declare function loadContext(
|
|
36
|
+
export declare function loadContext(params: LoadContextParams): Promise<LoadContext>;
|
|
32
37
|
/**
|
|
33
38
|
* This is the crux of the Docusaurus server-side. It reads everything it needs—
|
|
34
39
|
* code translations, config file, plugin modules... Plugins then use their
|
|
35
40
|
* lifecycles to generate content and other data. It is side-effect-ful because
|
|
36
41
|
* it generates temp files in the `.docusaurus` folder for the bundler.
|
|
37
42
|
*/
|
|
38
|
-
export declare function
|
|
43
|
+
export declare function loadSite(params: LoadContextParams): Promise<Site>;
|
|
44
|
+
export declare function reloadSite(site: Site): Promise<Site>;
|
|
45
|
+
export declare function reloadSitePlugin(site: Site, pluginIdentifier: PluginIdentifier): Promise<Site>;
|
|
@@ -0,0 +1,164 @@
|
|
|
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.reloadSitePlugin = exports.reloadSite = exports.loadSite = exports.loadContext = 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 combine_promises_1 = tslib_1.__importDefault(require("combine-promises"));
|
|
14
|
+
const config_1 = require("./config");
|
|
15
|
+
const clientModules_1 = require("./clientModules");
|
|
16
|
+
const plugins_1 = require("./plugins/plugins");
|
|
17
|
+
const htmlTags_1 = require("./htmlTags");
|
|
18
|
+
const siteMetadata_1 = require("./siteMetadata");
|
|
19
|
+
const i18n_1 = require("./i18n");
|
|
20
|
+
const translations_1 = require("./translations/translations");
|
|
21
|
+
const utils_2 = require("../utils");
|
|
22
|
+
const codegen_1 = require("./codegen/codegen");
|
|
23
|
+
const routes_1 = require("./routes");
|
|
24
|
+
/**
|
|
25
|
+
* Loading context is the very first step in site building. Its params are
|
|
26
|
+
* directly acquired from CLI options. It mainly loads `siteConfig` and the i18n
|
|
27
|
+
* context (which includes code translations). The `LoadContext` will be passed
|
|
28
|
+
* to plugin constructors.
|
|
29
|
+
*/
|
|
30
|
+
async function loadContext(params) {
|
|
31
|
+
const { siteDir, outDir: baseOutDir = utils_1.DEFAULT_BUILD_DIR_NAME, locale, config: customConfigFilePath, } = params;
|
|
32
|
+
const generatedFilesDir = path_1.default.resolve(siteDir, utils_1.GENERATED_FILES_DIR_NAME);
|
|
33
|
+
const { siteVersion, loadSiteConfig: { siteConfig: initialSiteConfig, siteConfigPath }, } = await (0, combine_promises_1.default)({
|
|
34
|
+
siteVersion: (0, siteMetadata_1.loadSiteVersion)(siteDir),
|
|
35
|
+
loadSiteConfig: (0, config_1.loadSiteConfig)({
|
|
36
|
+
siteDir,
|
|
37
|
+
customConfigFilePath,
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
const i18n = await (0, i18n_1.loadI18n)(initialSiteConfig, { locale });
|
|
41
|
+
const baseUrl = (0, utils_1.localizePath)({
|
|
42
|
+
path: initialSiteConfig.baseUrl,
|
|
43
|
+
i18n,
|
|
44
|
+
options: params,
|
|
45
|
+
pathType: 'url',
|
|
46
|
+
});
|
|
47
|
+
const outDir = (0, utils_1.localizePath)({
|
|
48
|
+
path: path_1.default.resolve(siteDir, baseOutDir),
|
|
49
|
+
i18n,
|
|
50
|
+
options: params,
|
|
51
|
+
pathType: 'fs',
|
|
52
|
+
});
|
|
53
|
+
const localizationDir = path_1.default.resolve(siteDir, i18n.path, i18n.localeConfigs[i18n.currentLocale].path);
|
|
54
|
+
const siteConfig = { ...initialSiteConfig, baseUrl };
|
|
55
|
+
const codeTranslations = await (0, translations_1.loadSiteCodeTranslations)({ localizationDir });
|
|
56
|
+
return {
|
|
57
|
+
siteDir,
|
|
58
|
+
siteVersion,
|
|
59
|
+
generatedFilesDir,
|
|
60
|
+
localizationDir,
|
|
61
|
+
siteConfig,
|
|
62
|
+
siteConfigPath,
|
|
63
|
+
outDir,
|
|
64
|
+
baseUrl,
|
|
65
|
+
i18n,
|
|
66
|
+
codeTranslations,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
exports.loadContext = loadContext;
|
|
70
|
+
function createSiteProps(params) {
|
|
71
|
+
const { plugins, routes, context } = params;
|
|
72
|
+
const { generatedFilesDir, siteDir, siteVersion, siteConfig, siteConfigPath, outDir, baseUrl, i18n, localizationDir, codeTranslations: siteCodeTranslations, } = context;
|
|
73
|
+
const { headTags, preBodyTags, postBodyTags } = (0, htmlTags_1.loadHtmlTags)(plugins);
|
|
74
|
+
const siteMetadata = (0, siteMetadata_1.createSiteMetadata)({ plugins, siteVersion });
|
|
75
|
+
const codeTranslations = {
|
|
76
|
+
...(0, translations_1.getPluginsDefaultCodeTranslations)({ plugins }),
|
|
77
|
+
...siteCodeTranslations,
|
|
78
|
+
};
|
|
79
|
+
(0, routes_1.handleDuplicateRoutes)(routes, siteConfig.onDuplicateRoutes);
|
|
80
|
+
const routesPaths = (0, routes_1.getRoutesPaths)(routes, baseUrl);
|
|
81
|
+
return {
|
|
82
|
+
siteConfig,
|
|
83
|
+
siteConfigPath,
|
|
84
|
+
siteMetadata,
|
|
85
|
+
siteVersion,
|
|
86
|
+
siteDir,
|
|
87
|
+
outDir,
|
|
88
|
+
baseUrl,
|
|
89
|
+
i18n,
|
|
90
|
+
localizationDir,
|
|
91
|
+
generatedFilesDir,
|
|
92
|
+
routes,
|
|
93
|
+
routesPaths,
|
|
94
|
+
plugins,
|
|
95
|
+
headTags,
|
|
96
|
+
preBodyTags,
|
|
97
|
+
postBodyTags,
|
|
98
|
+
codeTranslations,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// TODO global data should be part of site props?
|
|
102
|
+
async function createSiteFiles({ site, globalData, }) {
|
|
103
|
+
return utils_2.PerfLogger.async('Create site files', async () => {
|
|
104
|
+
const { props: { plugins, generatedFilesDir, siteConfig, siteMetadata, i18n, codeTranslations, routes, baseUrl, }, } = site;
|
|
105
|
+
const clientModules = (0, clientModules_1.getAllClientModules)(plugins);
|
|
106
|
+
await (0, codegen_1.generateSiteFiles)({
|
|
107
|
+
generatedFilesDir,
|
|
108
|
+
clientModules,
|
|
109
|
+
siteConfig,
|
|
110
|
+
siteMetadata,
|
|
111
|
+
i18n,
|
|
112
|
+
codeTranslations,
|
|
113
|
+
globalData,
|
|
114
|
+
routes,
|
|
115
|
+
baseUrl,
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* This is the crux of the Docusaurus server-side. It reads everything it needs—
|
|
121
|
+
* code translations, config file, plugin modules... Plugins then use their
|
|
122
|
+
* lifecycles to generate content and other data. It is side-effect-ful because
|
|
123
|
+
* it generates temp files in the `.docusaurus` folder for the bundler.
|
|
124
|
+
*/
|
|
125
|
+
async function loadSite(params) {
|
|
126
|
+
const context = await utils_2.PerfLogger.async('Load context', () => loadContext(params));
|
|
127
|
+
const { plugins, routes, globalData } = await (0, plugins_1.loadPlugins)(context);
|
|
128
|
+
const props = await createSiteProps({ plugins, routes, globalData, context });
|
|
129
|
+
const site = { props, params };
|
|
130
|
+
await createSiteFiles({
|
|
131
|
+
site,
|
|
132
|
+
globalData,
|
|
133
|
+
});
|
|
134
|
+
return site;
|
|
135
|
+
}
|
|
136
|
+
exports.loadSite = loadSite;
|
|
137
|
+
async function reloadSite(site) {
|
|
138
|
+
// TODO this can be optimized, for example:
|
|
139
|
+
// - plugins loading same data as before should not recreate routes/bundles
|
|
140
|
+
// - codegen does not need to re-run if nothing changed
|
|
141
|
+
return loadSite(site.params);
|
|
142
|
+
}
|
|
143
|
+
exports.reloadSite = reloadSite;
|
|
144
|
+
async function reloadSitePlugin(site, pluginIdentifier) {
|
|
145
|
+
const { plugins, routes, globalData } = await (0, plugins_1.reloadPlugin)({
|
|
146
|
+
pluginIdentifier,
|
|
147
|
+
plugins: site.props.plugins,
|
|
148
|
+
context: site.props,
|
|
149
|
+
});
|
|
150
|
+
const newProps = await createSiteProps({
|
|
151
|
+
plugins,
|
|
152
|
+
routes,
|
|
153
|
+
globalData,
|
|
154
|
+
context: site.props, // Props extends Context
|
|
155
|
+
});
|
|
156
|
+
const newSite = {
|
|
157
|
+
props: newProps,
|
|
158
|
+
params: site.params,
|
|
159
|
+
};
|
|
160
|
+
// TODO optimize, bypass useless codegen if new site is similar to old site
|
|
161
|
+
await createSiteFiles({ site: newSite, globalData });
|
|
162
|
+
return newSite;
|
|
163
|
+
}
|
|
164
|
+
exports.reloadSitePlugin = reloadSitePlugin;
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { LoadedPlugin, PluginVersionInformation, SiteMetadata } from '@docusaurus/types';
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
8
|
+
export declare function loadSiteVersion(siteDir: string): Promise<string | undefined>;
|
|
9
|
+
export declare function loadPluginVersion(pluginPath: string, siteDir: string): Promise<PluginVersionInformation>;
|
|
10
|
+
export declare function createSiteMetadata({ siteVersion, plugins, }: {
|
|
11
|
+
siteVersion: string | undefined;
|
|
10
12
|
plugins: LoadedPlugin[];
|
|
11
|
-
|
|
12
|
-
}): Promise<SiteMetadata>;
|
|
13
|
+
}): SiteMetadata;
|
|
@@ -6,23 +6,27 @@
|
|
|
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.createSiteMetadata = exports.loadPluginVersion = exports.loadSiteVersion = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
12
12
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
13
13
|
const utils_1 = require("@docusaurus/utils");
|
|
14
|
-
async function
|
|
14
|
+
async function loadPackageJsonVersion(packageJsonPath) {
|
|
15
15
|
if (await fs_extra_1.default.pathExists(packageJsonPath)) {
|
|
16
16
|
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
|
|
17
17
|
return require(packageJsonPath).version;
|
|
18
18
|
}
|
|
19
19
|
return undefined;
|
|
20
20
|
}
|
|
21
|
-
async function
|
|
21
|
+
async function loadPackageJsonName(packageJsonPath) {
|
|
22
22
|
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
|
|
23
23
|
return require(packageJsonPath).name;
|
|
24
24
|
}
|
|
25
|
-
async function
|
|
25
|
+
async function loadSiteVersion(siteDir) {
|
|
26
|
+
return loadPackageJsonVersion(path_1.default.join(siteDir, 'package.json'));
|
|
27
|
+
}
|
|
28
|
+
exports.loadSiteVersion = loadSiteVersion;
|
|
29
|
+
async function loadPluginVersion(pluginPath, siteDir) {
|
|
26
30
|
let potentialPluginPackageJsonDirectory = path_1.default.dirname(pluginPath);
|
|
27
31
|
while (potentialPluginPackageJsonDirectory !== '/') {
|
|
28
32
|
const packageJsonPath = path_1.default.join(potentialPluginPackageJsonDirectory, 'package.json');
|
|
@@ -35,8 +39,8 @@ async function getPluginVersion(pluginPath, siteDir) {
|
|
|
35
39
|
}
|
|
36
40
|
return {
|
|
37
41
|
type: 'package',
|
|
38
|
-
name: await
|
|
39
|
-
version: await
|
|
42
|
+
name: await loadPackageJsonName(packageJsonPath),
|
|
43
|
+
version: await loadPackageJsonVersion(packageJsonPath),
|
|
40
44
|
};
|
|
41
45
|
}
|
|
42
46
|
potentialPluginPackageJsonDirectory = path_1.default.dirname(potentialPluginPackageJsonDirectory);
|
|
@@ -46,7 +50,7 @@ async function getPluginVersion(pluginPath, siteDir) {
|
|
|
46
50
|
// script in the parent directory of the site.
|
|
47
51
|
return { type: 'local' };
|
|
48
52
|
}
|
|
49
|
-
exports.
|
|
53
|
+
exports.loadPluginVersion = loadPluginVersion;
|
|
50
54
|
/**
|
|
51
55
|
* We want all `@docusaurus/*` packages to have the exact same version!
|
|
52
56
|
* @see https://github.com/facebook/docusaurus/issues/3371
|
|
@@ -65,10 +69,10 @@ Maybe you want to check, or regenerate your yarn.lock or package-lock.json file?
|
|
|
65
69
|
}
|
|
66
70
|
});
|
|
67
71
|
}
|
|
68
|
-
|
|
72
|
+
function createSiteMetadata({ siteVersion, plugins, }) {
|
|
69
73
|
const siteMetadata = {
|
|
70
74
|
docusaurusVersion: utils_1.DOCUSAURUS_VERSION,
|
|
71
|
-
siteVersion
|
|
75
|
+
siteVersion,
|
|
72
76
|
pluginVersions: Object.fromEntries(plugins
|
|
73
77
|
.filter(({ version: { type } }) => type !== 'synthetic')
|
|
74
78
|
.map(({ name, version }) => [name, version])),
|
|
@@ -76,4 +80,4 @@ async function loadSiteMetadata({ plugins, siteDir, }) {
|
|
|
76
80
|
checkDocusaurusPackagesVersion(siteMetadata);
|
|
77
81
|
return siteMetadata;
|
|
78
82
|
}
|
|
79
|
-
exports.
|
|
83
|
+
exports.createSiteMetadata = createSiteMetadata;
|
|
@@ -4,7 +4,7 @@
|
|
|
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 { TranslationFileContent, TranslationFile, CodeTranslations, InitializedPlugin } from '@docusaurus/types';
|
|
7
|
+
import type { TranslationFileContent, TranslationFile, CodeTranslations, InitializedPlugin, LoadedPlugin } from '@docusaurus/types';
|
|
8
8
|
export type WriteTranslationsOptions = {
|
|
9
9
|
override?: boolean;
|
|
10
10
|
messagePrefix?: string;
|
|
@@ -23,9 +23,16 @@ export declare function localizePluginTranslationFile({ localizationDir, plugin,
|
|
|
23
23
|
plugin: InitializedPlugin;
|
|
24
24
|
translationFile: TranslationFile;
|
|
25
25
|
}): Promise<TranslationFile>;
|
|
26
|
-
export declare function
|
|
26
|
+
export declare function mergeCodeTranslations(codeTranslations: CodeTranslations[]): CodeTranslations;
|
|
27
|
+
export declare function loadPluginsDefaultCodeTranslationMessages(plugins: InitializedPlugin[]): Promise<CodeTranslations>;
|
|
28
|
+
export declare function getPluginsDefaultCodeTranslations({ plugins, }: {
|
|
29
|
+
plugins: LoadedPlugin[];
|
|
30
|
+
}): CodeTranslations;
|
|
27
31
|
export declare function applyDefaultCodeTranslations({ extractedCodeTranslations, defaultCodeMessages, }: {
|
|
28
32
|
extractedCodeTranslations: TranslationFileContent;
|
|
29
33
|
defaultCodeMessages: CodeTranslations;
|
|
30
34
|
}): TranslationFileContent;
|
|
35
|
+
export declare function loadSiteCodeTranslations({ localizationDir, }: {
|
|
36
|
+
localizationDir: string;
|
|
37
|
+
}): Promise<CodeTranslations>;
|
|
31
38
|
export {};
|
|
@@ -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.applyDefaultCodeTranslations = exports.
|
|
9
|
+
exports.loadSiteCodeTranslations = exports.applyDefaultCodeTranslations = exports.getPluginsDefaultCodeTranslations = exports.loadPluginsDefaultCodeTranslationMessages = exports.mergeCodeTranslations = exports.localizePluginTranslationFile = exports.writePluginTranslations = exports.writeCodeTranslations = exports.readCodeTranslationFileContent = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
12
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
@@ -145,11 +145,22 @@ async function localizePluginTranslationFile({ localizationDir, plugin, translat
|
|
|
145
145
|
return translationFile;
|
|
146
146
|
}
|
|
147
147
|
exports.localizePluginTranslationFile = localizePluginTranslationFile;
|
|
148
|
-
|
|
148
|
+
function mergeCodeTranslations(codeTranslations) {
|
|
149
|
+
return codeTranslations.reduce((allCodeTranslations, current) => ({
|
|
150
|
+
...allCodeTranslations,
|
|
151
|
+
...current,
|
|
152
|
+
}), {});
|
|
153
|
+
}
|
|
154
|
+
exports.mergeCodeTranslations = mergeCodeTranslations;
|
|
155
|
+
async function loadPluginsDefaultCodeTranslationMessages(plugins) {
|
|
149
156
|
const pluginsMessages = await Promise.all(plugins.map((plugin) => plugin.getDefaultCodeTranslationMessages?.() ?? {}));
|
|
150
|
-
return pluginsMessages
|
|
157
|
+
return mergeCodeTranslations(pluginsMessages);
|
|
158
|
+
}
|
|
159
|
+
exports.loadPluginsDefaultCodeTranslationMessages = loadPluginsDefaultCodeTranslationMessages;
|
|
160
|
+
function getPluginsDefaultCodeTranslations({ plugins, }) {
|
|
161
|
+
return mergeCodeTranslations(plugins.map((p) => p.defaultCodeTranslations));
|
|
151
162
|
}
|
|
152
|
-
exports.
|
|
163
|
+
exports.getPluginsDefaultCodeTranslations = getPluginsDefaultCodeTranslations;
|
|
153
164
|
function applyDefaultCodeTranslations({ extractedCodeTranslations, defaultCodeMessages, }) {
|
|
154
165
|
const unusedDefaultCodeMessages = lodash_1.default.difference(Object.keys(defaultCodeMessages), Object.keys(extractedCodeTranslations));
|
|
155
166
|
if (unusedDefaultCodeMessages.length > 0) {
|
|
@@ -162,3 +173,9 @@ Please report this Docusaurus issue. name=${unusedDefaultCodeMessages}`;
|
|
|
162
173
|
}));
|
|
163
174
|
}
|
|
164
175
|
exports.applyDefaultCodeTranslations = applyDefaultCodeTranslations;
|
|
176
|
+
async function loadSiteCodeTranslations({ localizationDir, }) {
|
|
177
|
+
const codeTranslationFileContent = (await readCodeTranslationFileContent({ localizationDir })) ?? {};
|
|
178
|
+
// We only need key->message for code translations
|
|
179
|
+
return lodash_1.default.mapValues(codeTranslationFileContent, (value) => value.message);
|
|
180
|
+
}
|
|
181
|
+
exports.loadSiteCodeTranslations = loadSiteCodeTranslations;
|
package/lib/server/utils.d.ts
CHANGED
|
@@ -5,6 +5,4 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import { Globby } from '@docusaurus/utils';
|
|
8
|
-
import type { RouteConfig } from '@docusaurus/types';
|
|
9
|
-
export declare function getAllFinalRoutes(routeConfig: RouteConfig[]): RouteConfig[];
|
|
10
8
|
export declare function safeGlobby(patterns: string[], options?: Globby.GlobbyOptions): Promise<string[]>;
|
package/lib/server/utils.js
CHANGED
|
@@ -6,18 +6,10 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.safeGlobby =
|
|
9
|
+
exports.safeGlobby = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
12
|
const utils_1 = require("@docusaurus/utils");
|
|
13
|
-
// Recursively get the final routes (routes with no subroutes)
|
|
14
|
-
function getAllFinalRoutes(routeConfig) {
|
|
15
|
-
function getFinalRoutes(route) {
|
|
16
|
-
return route.routes ? route.routes.flatMap(getFinalRoutes) : [route];
|
|
17
|
-
}
|
|
18
|
-
return routeConfig.flatMap(getFinalRoutes);
|
|
19
|
-
}
|
|
20
|
-
exports.getAllFinalRoutes = getAllFinalRoutes;
|
|
21
13
|
// Globby that fix Windows path patterns
|
|
22
14
|
// See https://github.com/facebook/docusaurus/pull/4222#issuecomment-795517329
|
|
23
15
|
async function safeGlobby(patterns, options) {
|
package/lib/ssg.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
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 { AppRenderer, SiteCollectedData } from './common';
|
|
8
|
+
import type { Manifest } from 'react-loadable-ssr-addon-v5-slorber';
|
|
9
|
+
import type { SSRTemplateCompiled } from './templates/templates';
|
|
10
|
+
export type SSGParams = {
|
|
11
|
+
trailingSlash: boolean | undefined;
|
|
12
|
+
manifest: Manifest;
|
|
13
|
+
headTags: string;
|
|
14
|
+
preBodyTags: string;
|
|
15
|
+
postBodyTags: string;
|
|
16
|
+
outDir: string;
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
noIndex: boolean;
|
|
19
|
+
DOCUSAURUS_VERSION: string;
|
|
20
|
+
ssrTemplate: SSRTemplateCompiled;
|
|
21
|
+
};
|
|
22
|
+
export declare function loadAppRenderer({ serverBundlePath, }: {
|
|
23
|
+
serverBundlePath: string;
|
|
24
|
+
}): Promise<AppRenderer>;
|
|
25
|
+
export declare function generateStaticFiles({ pathnames, renderer, params, }: {
|
|
26
|
+
pathnames: string[];
|
|
27
|
+
renderer: AppRenderer;
|
|
28
|
+
params: SSGParams;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
collectedData: SiteCollectedData;
|
|
31
|
+
}>;
|