@docusaurus/core 0.0.0-4803 → 0.0.0-4807
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/lib/client/docusaurus.js +4 -6
- package/lib/client/exports/ComponentCreator.js +3 -18
- package/lib/client/flat.d.ts +10 -2
- package/lib/client/flat.js +8 -0
- package/lib/server/plugins/index.d.ts +2 -1
- package/lib/server/plugins/index.js +26 -35
- package/lib/server/plugins/routeConfig.d.ts +1 -0
- package/lib/server/plugins/routeConfig.js +1 -0
- package/lib/server/routes.d.ts +42 -9
- package/lib/server/routes.js +115 -90
- package/lib/webpack/utils.d.ts +3 -3
- package/package.json +10 -10
package/lib/client/docusaurus.js
CHANGED
|
@@ -17,15 +17,13 @@ const isSlowConnection = () => navigator.connection?.effectiveType.includes('2g'
|
|
|
17
17
|
navigator.connection?.saveData;
|
|
18
18
|
const canPrefetch = (routePath) => !isSlowConnection() && !loaded[routePath] && !fetched[routePath];
|
|
19
19
|
const canPreload = (routePath) => !isSlowConnection() && !loaded[routePath];
|
|
20
|
+
const getChunkNamesToLoad = (path) => Object.entries(routesChunkNames)
|
|
21
|
+
.filter(
|
|
20
22
|
// Remove the last part containing the route hash
|
|
21
23
|
// input: /blog/2018/12/14/Happy-First-Birthday-Slash-fe9
|
|
22
24
|
// output: /blog/2018/12/14/Happy-First-Birthday-Slash
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
.filter(([routeNameWithHash]) => removeRouteNameHash(routeNameWithHash) === path)
|
|
26
|
-
.flatMap(([, routeChunks]) =>
|
|
27
|
-
// flat() is useful for nested chunk names, it's not like array.flat()
|
|
28
|
-
Object.values(flat(routeChunks)));
|
|
25
|
+
([routeNameWithHash]) => routeNameWithHash.replace(/-[^-]+$/, '') === path)
|
|
26
|
+
.flatMap(([, routeChunks]) => Object.values(flat(routeChunks)));
|
|
29
27
|
const docusaurus = {
|
|
30
28
|
prefetch: (routePath) => {
|
|
31
29
|
if (!canPrefetch(routePath)) {
|
|
@@ -26,26 +26,11 @@ export default function ComponentCreator(path, hash) {
|
|
|
26
26
|
},
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
-
const
|
|
30
|
-
const chunkNames = routesChunkNames[chunkNamesKey];
|
|
31
|
-
const optsModules = [];
|
|
32
|
-
const optsWebpack = [];
|
|
29
|
+
const chunkNames = routesChunkNames[`${path}-${hash}`];
|
|
33
30
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
31
|
const optsLoader = {};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Example:
|
|
38
|
-
- optsLoader:
|
|
39
|
-
{
|
|
40
|
-
component: () => import('./Pages.js'),
|
|
41
|
-
content.foo: () => import('./doc1.md'),
|
|
42
|
-
}
|
|
43
|
-
- optsModules: ['./Pages.js', './doc1.md']
|
|
44
|
-
- optsWebpack: [
|
|
45
|
-
require.resolveWeak('./Pages.js'),
|
|
46
|
-
require.resolveWeak('./doc1.md'),
|
|
47
|
-
]
|
|
48
|
-
*/
|
|
32
|
+
const optsModules = [];
|
|
33
|
+
const optsWebpack = [];
|
|
49
34
|
const flatChunkNames = flat(chunkNames);
|
|
50
35
|
Object.entries(flatChunkNames).forEach(([key, chunkName]) => {
|
|
51
36
|
const chunkRegistry = registry[chunkName];
|
package/lib/client/flat.d.ts
CHANGED
|
@@ -4,7 +4,15 @@
|
|
|
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 {
|
|
8
|
-
|
|
7
|
+
import type { ChunkNames } from '@docusaurus/types';
|
|
8
|
+
/**
|
|
9
|
+
* Takes a tree, and flattens it into a map of keyPath -> value.
|
|
10
|
+
*
|
|
11
|
+
* ```js
|
|
12
|
+
* flat({ a: { b: 1 } }) === { "a.b": 1 };
|
|
13
|
+
* flat({ a: [1, 2] }) === { "a.0": 1, "a.1": 2 };
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export default function flat(target: ChunkNames): {
|
|
9
17
|
[keyPath: string]: string;
|
|
10
18
|
};
|
package/lib/client/flat.js
CHANGED
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
const isTree = (x) => typeof x === 'object' && !!x && Object.keys(x).length > 0;
|
|
8
|
+
/**
|
|
9
|
+
* Takes a tree, and flattens it into a map of keyPath -> value.
|
|
10
|
+
*
|
|
11
|
+
* ```js
|
|
12
|
+
* flat({ a: { b: 1 } }) === { "a.b": 1 };
|
|
13
|
+
* flat({ a: [1, 2] }) === { "a.0": 1, "a.1": 2 };
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
8
16
|
export default function flat(target) {
|
|
9
17
|
const delimiter = '.';
|
|
10
18
|
const output = {};
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
import type { LoadContext, RouteConfig, GlobalData, ThemeConfig, LoadedPlugin } from '@docusaurus/types';
|
|
8
8
|
/**
|
|
9
9
|
* Initializes the plugins, runs `loadContent`, `translateContent`,
|
|
10
|
-
* `contentLoaded`, and `translateThemeConfig`.
|
|
10
|
+
* `contentLoaded`, and `translateThemeConfig`. Because `contentLoaded` is
|
|
11
|
+
* side-effect-ful (it generates temp files), so is this function.
|
|
11
12
|
*/
|
|
12
13
|
export declare function loadPlugins(context: LoadContext): Promise<{
|
|
13
14
|
plugins: LoadedPlugin[];
|
|
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.loadPlugins = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const utils_1 = require("@docusaurus/utils");
|
|
12
|
-
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
13
12
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
14
13
|
const init_1 = require("./init");
|
|
15
14
|
const synthetic_1 = require("./synthetic");
|
|
@@ -19,7 +18,8 @@ const translations_1 = require("../translations/translations");
|
|
|
19
18
|
const routeConfig_1 = require("./routeConfig");
|
|
20
19
|
/**
|
|
21
20
|
* Initializes the plugins, runs `loadContent`, `translateContent`,
|
|
22
|
-
* `contentLoaded`, and `translateThemeConfig`.
|
|
21
|
+
* `contentLoaded`, and `translateThemeConfig`. Because `contentLoaded` is
|
|
22
|
+
* side-effect-ful (it generates temp files), so is this function.
|
|
23
23
|
*/
|
|
24
24
|
async function loadPlugins(context) {
|
|
25
25
|
// 1. Plugin Lifecycle - Initialization/Constructor.
|
|
@@ -64,46 +64,37 @@ async function loadPlugins(context) {
|
|
|
64
64
|
}
|
|
65
65
|
const pluginId = plugin.options.id;
|
|
66
66
|
// plugins data files are namespaced by pluginName/pluginId
|
|
67
|
-
const
|
|
68
|
-
const dataDir = path_1.default.join(dataDirRoot, pluginId);
|
|
69
|
-
const createData = async (name, data) => {
|
|
70
|
-
const modulePath = path_1.default.join(dataDir, name);
|
|
71
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(modulePath));
|
|
72
|
-
await (0, utils_1.generate)(dataDir, name, data);
|
|
73
|
-
return modulePath;
|
|
74
|
-
};
|
|
67
|
+
const dataDir = path_1.default.join(context.generatedFilesDir, plugin.name, pluginId);
|
|
75
68
|
// TODO this would be better to do all that in the codegen phase
|
|
76
69
|
// TODO handle context for nested routes
|
|
77
70
|
const pluginRouteContext = {
|
|
78
71
|
plugin: { name: plugin.name, id: pluginId },
|
|
79
72
|
data: undefined, // TODO allow plugins to provide context data
|
|
80
73
|
};
|
|
81
|
-
const pluginRouteContextModulePath =
|
|
82
|
-
|
|
83
|
-
// Trailing slash behavior is handled in a generic way for all plugins
|
|
84
|
-
const finalRouteConfig = (0, routeConfig_1.applyRouteTrailingSlash)(initialRouteConfig, {
|
|
85
|
-
trailingSlash: context.siteConfig.trailingSlash,
|
|
86
|
-
baseUrl: context.siteConfig.baseUrl,
|
|
87
|
-
});
|
|
88
|
-
pluginsRouteConfigs.push({
|
|
89
|
-
...finalRouteConfig,
|
|
90
|
-
modules: {
|
|
91
|
-
...finalRouteConfig.modules,
|
|
92
|
-
__routeContextModule: pluginRouteContextModulePath,
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
};
|
|
96
|
-
// the plugins global data are namespaced to avoid data conflicts:
|
|
97
|
-
// - by plugin name
|
|
98
|
-
// - by plugin id (allow using multiple instances of the same plugin)
|
|
99
|
-
const setGlobalData = (data) => {
|
|
100
|
-
globalData[plugin.name] = globalData[plugin.name] ?? {};
|
|
101
|
-
globalData[plugin.name][pluginId] = data;
|
|
102
|
-
};
|
|
74
|
+
const pluginRouteContextModulePath = path_1.default.join(dataDir, `${(0, utils_1.docuHash)('pluginRouteContextModule')}.json`);
|
|
75
|
+
await (0, utils_1.generate)('/', pluginRouteContextModulePath, JSON.stringify(pluginRouteContext, null, 2));
|
|
103
76
|
const actions = {
|
|
104
|
-
addRoute
|
|
105
|
-
|
|
106
|
-
|
|
77
|
+
addRoute(initialRouteConfig) {
|
|
78
|
+
// Trailing slash behavior is handled generically for all plugins
|
|
79
|
+
const finalRouteConfig = (0, routeConfig_1.applyRouteTrailingSlash)(initialRouteConfig, context.siteConfig);
|
|
80
|
+
pluginsRouteConfigs.push({
|
|
81
|
+
...finalRouteConfig,
|
|
82
|
+
modules: {
|
|
83
|
+
...finalRouteConfig.modules,
|
|
84
|
+
__routeContextModule: pluginRouteContextModulePath,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
async createData(name, data) {
|
|
89
|
+
const modulePath = path_1.default.join(dataDir, name);
|
|
90
|
+
await (0, utils_1.generate)(dataDir, name, data);
|
|
91
|
+
return modulePath;
|
|
92
|
+
},
|
|
93
|
+
setGlobalData(data) {
|
|
94
|
+
var _a;
|
|
95
|
+
globalData[_a = plugin.name] ?? (globalData[_a] = {});
|
|
96
|
+
globalData[plugin.name][pluginId] = data;
|
|
97
|
+
},
|
|
107
98
|
};
|
|
108
99
|
const translatedContent = plugin.translateContent?.({ content, translationFiles }) ?? content;
|
|
109
100
|
await plugin.contentLoaded({
|
|
@@ -6,5 +6,6 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { RouteConfig } from '@docusaurus/types';
|
|
8
8
|
import { type ApplyTrailingSlashParams } from '@docusaurus/utils-common';
|
|
9
|
+
/** Recursively applies trailing slash config to all nested routes. */
|
|
9
10
|
export declare function applyRouteTrailingSlash(route: RouteConfig, params: ApplyTrailingSlashParams): RouteConfig;
|
|
10
11
|
export declare function sortConfig(routeConfigs: RouteConfig[], baseUrl?: string): void;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.sortConfig = exports.applyRouteTrailingSlash = void 0;
|
|
10
10
|
const utils_common_1 = require("@docusaurus/utils-common");
|
|
11
|
+
/** Recursively applies trailing slash config to all nested routes. */
|
|
11
12
|
function applyRouteTrailingSlash(route, params) {
|
|
12
13
|
return {
|
|
13
14
|
...route,
|
package/lib/server/routes.d.ts
CHANGED
|
@@ -4,15 +4,48 @@
|
|
|
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 {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
registry: {
|
|
11
|
-
[chunkName: string]: ChunkRegistry;
|
|
12
|
-
};
|
|
7
|
+
import type { RouteConfig, RouteChunkNames, ReportingSeverity } from '@docusaurus/types';
|
|
8
|
+
declare type LoadedRoutes = {
|
|
9
|
+
/** Serialized routes config that can be directly emitted into temp file. */
|
|
13
10
|
routesConfig: string;
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
/** @see {ChunkNames} */
|
|
12
|
+
routesChunkNames: RouteChunkNames;
|
|
13
|
+
/** A map from chunk name to module loaders. */
|
|
14
|
+
registry: {
|
|
15
|
+
[chunkName: string]: {
|
|
16
|
+
loader: string;
|
|
17
|
+
modulePath: string;
|
|
18
|
+
};
|
|
16
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
|
+
*/
|
|
17
26
|
routesPaths: string[];
|
|
18
|
-
}
|
|
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): Promise<LoadedRoutes>;
|
|
51
|
+
export {};
|
package/lib/server/routes.js
CHANGED
|
@@ -6,25 +6,64 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.loadRoutes = exports.handleDuplicateRoutes = void 0;
|
|
9
|
+
exports.loadRoutes = exports.handleDuplicateRoutes = exports.genChunkName = void 0;
|
|
10
|
+
const tslib_1 = require("tslib");
|
|
10
11
|
const utils_1 = require("@docusaurus/utils");
|
|
11
|
-
const
|
|
12
|
+
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
13
|
+
const querystring_1 = tslib_1.__importDefault(require("querystring"));
|
|
12
14
|
const utils_2 = require("./utils");
|
|
15
|
+
/** Indents every line of `str` by one level. */
|
|
13
16
|
function indent(str) {
|
|
14
|
-
|
|
15
|
-
return `${spaces}${str.replace(/\n/g, `\n${spaces}`)}`;
|
|
17
|
+
return ` ${str.replace(/\n/g, `\n `)}`;
|
|
16
18
|
}
|
|
17
|
-
|
|
19
|
+
const chunkNameCache = new Map();
|
|
20
|
+
/**
|
|
21
|
+
* Generates a unique chunk name that can be used in the chunk registry.
|
|
22
|
+
*
|
|
23
|
+
* @param modulePath A path to generate chunk name from. The actual value has no
|
|
24
|
+
* semantic significance.
|
|
25
|
+
* @param prefix A prefix to append to the chunk name, to avoid name clash.
|
|
26
|
+
* @param preferredName Chunk names default to `modulePath`, and this can supply
|
|
27
|
+
* a more human-readable name.
|
|
28
|
+
* @param shortId When `true`, the chunk name would only be a hash without any
|
|
29
|
+
* other characters. Useful for bundle size. Defaults to `true` in production.
|
|
30
|
+
*/
|
|
31
|
+
function genChunkName(modulePath, prefix, preferredName, shortId = process.env.NODE_ENV === 'production') {
|
|
32
|
+
let chunkName = chunkNameCache.get(modulePath);
|
|
33
|
+
if (!chunkName) {
|
|
34
|
+
if (shortId) {
|
|
35
|
+
chunkName = (0, utils_1.simpleHash)(modulePath, 8);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
let str = modulePath;
|
|
39
|
+
if (preferredName) {
|
|
40
|
+
const shortHash = (0, utils_1.simpleHash)(modulePath, 3);
|
|
41
|
+
str = `${preferredName}${shortHash}`;
|
|
42
|
+
}
|
|
43
|
+
const name = str === '/' ? 'index' : (0, utils_1.docuHash)(str);
|
|
44
|
+
chunkName = prefix ? `${prefix}---${name}` : name;
|
|
45
|
+
}
|
|
46
|
+
chunkNameCache.set(modulePath, chunkName);
|
|
47
|
+
}
|
|
48
|
+
return chunkName;
|
|
49
|
+
}
|
|
50
|
+
exports.genChunkName = genChunkName;
|
|
51
|
+
/**
|
|
52
|
+
* Takes a piece of route config, and serializes it into raw JS code. The shape
|
|
53
|
+
* is the same as react-router's `RouteConfig`. Formatting is similar to
|
|
54
|
+
* `JSON.stringify` but without all the quotes.
|
|
55
|
+
*/
|
|
56
|
+
function serializeRouteConfig({ routePath, routeHash, exact, subroutesCodeStrings, props, }) {
|
|
18
57
|
const parts = [
|
|
19
58
|
`path: '${routePath}'`,
|
|
20
|
-
`component: ComponentCreator('${routePath}','${routeHash}')`,
|
|
59
|
+
`component: ComponentCreator('${routePath}', '${routeHash}')`,
|
|
21
60
|
];
|
|
22
61
|
if (exact) {
|
|
23
62
|
parts.push(`exact: true`);
|
|
24
63
|
}
|
|
25
64
|
if (subroutesCodeStrings) {
|
|
26
65
|
parts.push(`routes: [
|
|
27
|
-
${indent(
|
|
66
|
+
${indent(subroutesCodeStrings.join(',\n'))}
|
|
28
67
|
]`);
|
|
29
68
|
}
|
|
30
69
|
Object.entries(props).forEach(([propName, propValue]) => {
|
|
@@ -52,54 +91,33 @@ ${indent((0, utils_1.removeSuffix)(subroutesCodeStrings.join(',\n'), ',\n'))}
|
|
|
52
91
|
${indent(parts.join(',\n'))}
|
|
53
92
|
}`;
|
|
54
93
|
}
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
component: ComponentCreator('*')
|
|
58
|
-
}`;
|
|
59
|
-
const RoutesImportsCode = [
|
|
60
|
-
`import React from 'react';`,
|
|
61
|
-
`import ComponentCreator from '@docusaurus/ComponentCreator';`,
|
|
62
|
-
].join('\n');
|
|
63
|
-
function isModule(value) {
|
|
64
|
-
if (typeof value === 'string') {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
if (typeof value === 'object' &&
|
|
94
|
+
const isModule = (value) => typeof value === 'string' ||
|
|
95
|
+
(typeof value === 'object' &&
|
|
68
96
|
// eslint-disable-next-line no-underscore-dangle
|
|
69
|
-
value?.__import
|
|
70
|
-
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
97
|
+
!!value?.__import);
|
|
98
|
+
/** Takes a {@link Module} and returns the string path it represents. */
|
|
75
99
|
function getModulePath(target) {
|
|
76
100
|
if (typeof target === 'string') {
|
|
77
101
|
return target;
|
|
78
102
|
}
|
|
79
|
-
const queryStr = target.query ? `?${
|
|
103
|
+
const queryStr = target.query ? `?${querystring_1.default.stringify(target.query)}` : '';
|
|
80
104
|
return `${target.path}${queryStr}`;
|
|
81
105
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (isModule(value)) {
|
|
92
|
-
const modulePath = getModulePath(value);
|
|
93
|
-
const chunkName = (0, utils_1.genChunkName)(modulePath, prefix, name);
|
|
94
|
-
const loader = `() => import(/* webpackChunkName: '${chunkName}' */ '${(0, utils_1.escapePath)(modulePath)}')`;
|
|
95
|
-
registry[chunkName] = { loader, modulePath };
|
|
106
|
+
function genChunkNames(routeModule, prefix, name, res) {
|
|
107
|
+
if (isModule(routeModule)) {
|
|
108
|
+
// This is a leaf node, no need to recurse
|
|
109
|
+
const modulePath = getModulePath(routeModule);
|
|
110
|
+
const chunkName = genChunkName(modulePath, prefix, name);
|
|
111
|
+
res.registry[chunkName] = {
|
|
112
|
+
loader: `() => import(/* webpackChunkName: '${chunkName}' */ '${(0, utils_1.escapePath)(modulePath)}')`,
|
|
113
|
+
modulePath,
|
|
114
|
+
};
|
|
96
115
|
return chunkName;
|
|
97
116
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return newValue;
|
|
117
|
+
if (Array.isArray(routeModule)) {
|
|
118
|
+
return routeModule.map((val, index) => genChunkNames(val, `${index}`, name, res));
|
|
119
|
+
}
|
|
120
|
+
return lodash_1.default.mapValues(routeModule, (v, key) => genChunkNames(v, key, name, res));
|
|
103
121
|
}
|
|
104
122
|
function handleDuplicateRoutes(pluginsRouteConfigs, onDuplicateRoutes) {
|
|
105
123
|
if (onDuplicateRoutes === 'ignore') {
|
|
@@ -124,55 +142,62 @@ This could lead to non-deterministic routing behavior.`;
|
|
|
124
142
|
}
|
|
125
143
|
}
|
|
126
144
|
exports.handleDuplicateRoutes = handleDuplicateRoutes;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
throw new Error(`Invalid route config: path must be a string and component is required.
|
|
145
|
+
/**
|
|
146
|
+
* This is the higher level overview of route code generation. For each route
|
|
147
|
+
* config node, it return the node's serialized form, and mutate `registry`,
|
|
148
|
+
* `routesPaths`, and `routesChunkNames` accordingly.
|
|
149
|
+
*/
|
|
150
|
+
function genRouteCode(routeConfig, res) {
|
|
151
|
+
const { path: routePath, component, modules = {}, routes: subroutes, priority, exact, ...props } = routeConfig;
|
|
152
|
+
if (typeof routePath !== 'string' || !component) {
|
|
153
|
+
throw new Error(`Invalid route config: path must be a string and component is required.
|
|
137
154
|
${JSON.stringify(routeConfig)}`);
|
|
138
|
-
}
|
|
139
|
-
// Collect all page paths for injecting it later in the plugin lifecycle
|
|
140
|
-
// This is useful for plugins like sitemaps, redirects etc...
|
|
141
|
-
// If a route has subroutes, it is not necessarily a valid page path (more
|
|
142
|
-
// likely to be a wrapper)
|
|
143
|
-
if (!subroutes) {
|
|
144
|
-
routesPaths.push(routePath);
|
|
145
|
-
}
|
|
146
|
-
// We hash the route to generate the key, because 2 routes can conflict with
|
|
147
|
-
// each others if they have the same path, ex: parent=/docs, child=/docs
|
|
148
|
-
// see https://github.com/facebook/docusaurus/issues/2917
|
|
149
|
-
const routeHash = (0, utils_1.simpleHash)(JSON.stringify(routeConfig), 3);
|
|
150
|
-
const chunkNamesKey = `${routePath}-${routeHash}`;
|
|
151
|
-
routesChunkNames[chunkNamesKey] = {
|
|
152
|
-
...genRouteChunkNames(registry, { component }, 'component', component),
|
|
153
|
-
...genRouteChunkNames(registry, modules, 'module', routePath),
|
|
154
|
-
};
|
|
155
|
-
return createRouteCodeString({
|
|
156
|
-
routePath: routeConfig.path.replace(/'/g, "\\'"),
|
|
157
|
-
routeHash,
|
|
158
|
-
exact,
|
|
159
|
-
subroutesCodeStrings: subroutes?.map(generateRouteCode),
|
|
160
|
-
props,
|
|
161
|
-
});
|
|
162
155
|
}
|
|
163
|
-
|
|
164
|
-
|
|
156
|
+
if (!subroutes) {
|
|
157
|
+
res.routesPaths.push(routePath);
|
|
158
|
+
}
|
|
159
|
+
const routeHash = (0, utils_1.simpleHash)(JSON.stringify(routeConfig), 3);
|
|
160
|
+
res.routesChunkNames[`${routePath}-${routeHash}`] = {
|
|
161
|
+
...genChunkNames({ component }, 'component', component, res),
|
|
162
|
+
...genChunkNames(modules, 'module', routePath, res),
|
|
163
|
+
};
|
|
164
|
+
return serializeRouteConfig({
|
|
165
|
+
routePath: routePath.replace(/'/g, "\\'"),
|
|
166
|
+
routeHash,
|
|
167
|
+
subroutesCodeStrings: subroutes?.map((r) => genRouteCode(r, res)),
|
|
168
|
+
exact,
|
|
169
|
+
props,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Routes are prepared into three temp files:
|
|
174
|
+
*
|
|
175
|
+
* - `routesConfig`, the route config passed to react-router. This file is kept
|
|
176
|
+
* minimal, because it can't be code-splitted.
|
|
177
|
+
* - `routesChunkNames`, a mapping from route paths (hashed) to code-splitted
|
|
178
|
+
* chunk names.
|
|
179
|
+
* - `registry`, a mapping from chunk names to options for react-loadable.
|
|
180
|
+
*/
|
|
181
|
+
async function loadRoutes(routeConfigs, baseUrl, onDuplicateRoutes) {
|
|
182
|
+
handleDuplicateRoutes(routeConfigs, onDuplicateRoutes);
|
|
183
|
+
const res = {
|
|
184
|
+
// To be written
|
|
185
|
+
routesConfig: '',
|
|
186
|
+
routesChunkNames: {},
|
|
187
|
+
registry: {},
|
|
188
|
+
routesPaths: [(0, utils_1.normalizeUrl)([baseUrl, '404.html'])],
|
|
189
|
+
};
|
|
190
|
+
res.routesConfig = `import React from 'react';
|
|
191
|
+
import ComponentCreator from '@docusaurus/ComponentCreator';
|
|
165
192
|
|
|
166
193
|
export default [
|
|
167
|
-
${indent(`${
|
|
168
|
-
|
|
194
|
+
${indent(`${routeConfigs.map((r) => genRouteCode(r, res)).join(',\n')},`)}
|
|
195
|
+
{
|
|
196
|
+
path: '*',
|
|
197
|
+
component: ComponentCreator('*'),
|
|
198
|
+
},
|
|
169
199
|
];
|
|
170
200
|
`;
|
|
171
|
-
return
|
|
172
|
-
registry,
|
|
173
|
-
routesConfig,
|
|
174
|
-
routesChunkNames,
|
|
175
|
-
routesPaths,
|
|
176
|
-
};
|
|
201
|
+
return res;
|
|
177
202
|
}
|
|
178
203
|
exports.loadRoutes = loadRoutes;
|
package/lib/webpack/utils.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
/// <reference types="node" />
|
|
8
8
|
import { type Configuration, type RuleSetRule, type WebpackPluginInstance } from 'webpack';
|
|
9
9
|
import type { TransformOptions } from '@babel/core';
|
|
10
|
-
import type {
|
|
10
|
+
import type { Plugin } from '@docusaurus/types';
|
|
11
11
|
export declare function getStyleLoaders(isServer: boolean, cssOptionsArg?: {
|
|
12
12
|
[key: string]: unknown;
|
|
13
13
|
}): RuleSetRule[];
|
|
@@ -29,8 +29,8 @@ export declare const getCustomizableJSLoader: (jsLoader?: "babel" | ((isServer:
|
|
|
29
29
|
* @param content content loaded by the plugin
|
|
30
30
|
* @returns final/ modified webpack config
|
|
31
31
|
*/
|
|
32
|
-
export declare function applyConfigureWebpack(configureWebpack:
|
|
33
|
-
export declare function applyConfigurePostCss(configurePostCss: NonNullable<
|
|
32
|
+
export declare function applyConfigureWebpack(configureWebpack: NonNullable<Plugin['configureWebpack']>, config: Configuration, isServer: boolean, jsLoader: 'babel' | ((isServer: boolean) => RuleSetRule) | undefined, content: unknown): Configuration;
|
|
33
|
+
export declare function applyConfigurePostCss(configurePostCss: NonNullable<Plugin['configurePostCss']>, config: Configuration): Configuration;
|
|
34
34
|
declare global {
|
|
35
35
|
interface Error {
|
|
36
36
|
/** @see https://webpack.js.org/api/node/#error-handling */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/core",
|
|
3
3
|
"description": "Easy to Maintain Open Source Documentation Websites",
|
|
4
|
-
"version": "0.0.0-
|
|
4
|
+
"version": "0.0.0-4807",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -41,13 +41,13 @@
|
|
|
41
41
|
"@babel/runtime": "^7.17.8",
|
|
42
42
|
"@babel/runtime-corejs3": "^7.17.8",
|
|
43
43
|
"@babel/traverse": "^7.17.3",
|
|
44
|
-
"@docusaurus/cssnano-preset": "0.0.0-
|
|
45
|
-
"@docusaurus/logger": "0.0.0-
|
|
46
|
-
"@docusaurus/mdx-loader": "0.0.0-
|
|
44
|
+
"@docusaurus/cssnano-preset": "0.0.0-4807",
|
|
45
|
+
"@docusaurus/logger": "0.0.0-4807",
|
|
46
|
+
"@docusaurus/mdx-loader": "0.0.0-4807",
|
|
47
47
|
"@docusaurus/react-loadable": "5.5.2",
|
|
48
|
-
"@docusaurus/utils": "0.0.0-
|
|
49
|
-
"@docusaurus/utils-common": "0.0.0-
|
|
50
|
-
"@docusaurus/utils-validation": "0.0.0-
|
|
48
|
+
"@docusaurus/utils": "0.0.0-4807",
|
|
49
|
+
"@docusaurus/utils-common": "0.0.0-4807",
|
|
50
|
+
"@docusaurus/utils-validation": "0.0.0-4807",
|
|
51
51
|
"@slorber/static-site-generator-webpack-plugin": "^4.0.4",
|
|
52
52
|
"@svgr/webpack": "^6.2.1",
|
|
53
53
|
"autoprefixer": "^10.4.4",
|
|
@@ -105,8 +105,8 @@
|
|
|
105
105
|
"webpackbar": "^5.0.2"
|
|
106
106
|
},
|
|
107
107
|
"devDependencies": {
|
|
108
|
-
"@docusaurus/module-type-aliases": "0.0.0-
|
|
109
|
-
"@docusaurus/types": "0.0.0-
|
|
108
|
+
"@docusaurus/module-type-aliases": "0.0.0-4807",
|
|
109
|
+
"@docusaurus/types": "0.0.0-4807",
|
|
110
110
|
"@types/detect-port": "^1.3.2",
|
|
111
111
|
"@types/nprogress": "^0.2.0",
|
|
112
112
|
"@types/react-dom": "^17.0.14",
|
|
@@ -127,5 +127,5 @@
|
|
|
127
127
|
"engines": {
|
|
128
128
|
"node": ">=14"
|
|
129
129
|
},
|
|
130
|
-
"gitHead": "
|
|
130
|
+
"gitHead": "9bb0a5cc35908e3d1ab5e8b3840180990c0e1e05"
|
|
131
131
|
}
|