@docusaurus/core 3.1.1 → 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.
Files changed (85) hide show
  1. package/bin/docusaurus.mjs +10 -5
  2. package/lib/client/{serverRenderer.d.ts → renderToHtml.d.ts} +1 -1
  3. package/lib/client/{serverRenderer.js → renderToHtml.js} +1 -1
  4. package/lib/client/serverEntry.d.ts +3 -4
  5. package/lib/client/serverEntry.js +12 -113
  6. package/lib/client/theme-fallback/Error/index.js +22 -8
  7. package/lib/commands/build.d.ts +3 -3
  8. package/lib/commands/build.js +133 -112
  9. package/lib/commands/deploy.d.ts +2 -2
  10. package/lib/commands/deploy.js +3 -3
  11. package/lib/commands/external.js +2 -2
  12. package/lib/commands/serve.d.ts +2 -2
  13. package/lib/commands/serve.js +4 -4
  14. package/lib/commands/{start.d.ts → start/start.d.ts} +3 -3
  15. package/lib/commands/start/start.js +47 -0
  16. package/lib/commands/start/utils.d.ts +31 -0
  17. package/lib/commands/start/utils.js +87 -0
  18. package/lib/commands/start/watcher.d.ts +42 -0
  19. package/lib/commands/start/watcher.js +78 -0
  20. package/lib/commands/start/webpack.d.ts +15 -0
  21. package/lib/commands/start/webpack.js +133 -0
  22. package/lib/commands/swizzle/common.d.ts +1 -0
  23. package/lib/commands/swizzle/common.js +1 -0
  24. package/lib/commands/swizzle/context.js +2 -2
  25. package/lib/commands/swizzle/index.js +32 -3
  26. package/lib/commands/writeHeadingIds.js +2 -2
  27. package/lib/commands/writeTranslations.d.ts +2 -2
  28. package/lib/commands/writeTranslations.js +3 -3
  29. package/lib/index.d.ts +1 -1
  30. package/lib/index.js +1 -1
  31. package/lib/server/brokenLinks.js +4 -4
  32. package/lib/server/clientModules.d.ts +1 -1
  33. package/lib/server/clientModules.js +3 -3
  34. package/lib/server/codegen/codegen.d.ts +20 -0
  35. package/lib/server/codegen/codegen.js +65 -0
  36. package/lib/server/codegen/codegenRoutes.d.ts +49 -0
  37. package/lib/server/codegen/codegenRoutes.js +190 -0
  38. package/lib/server/configValidation.js +6 -4
  39. package/lib/server/i18n.d.ts +2 -2
  40. package/lib/server/i18n.js +20 -2
  41. package/lib/server/plugins/actions.d.ts +19 -0
  42. package/lib/server/plugins/actions.js +62 -0
  43. package/lib/server/plugins/init.js +3 -3
  44. package/lib/server/plugins/plugins.d.ts +21 -0
  45. package/lib/server/plugins/plugins.js +188 -0
  46. package/lib/server/plugins/pluginsUtils.d.ts +16 -0
  47. package/lib/server/plugins/pluginsUtils.js +75 -0
  48. package/lib/server/plugins/routeConfig.d.ts +1 -1
  49. package/lib/server/plugins/routeConfig.js +4 -4
  50. package/lib/server/plugins/synthetic.d.ts +3 -3
  51. package/lib/server/plugins/synthetic.js +0 -2
  52. package/lib/server/routes.d.ts +3 -45
  53. package/lib/server/routes.js +16 -168
  54. package/lib/server/{index.d.ts → site.d.ts} +12 -5
  55. package/lib/server/site.js +164 -0
  56. package/lib/server/siteMetadata.d.ts +5 -4
  57. package/lib/server/siteMetadata.js +14 -10
  58. package/lib/server/translations/translations.d.ts +9 -2
  59. package/lib/server/translations/translations.js +21 -4
  60. package/lib/server/utils.d.ts +0 -2
  61. package/lib/server/utils.js +1 -9
  62. package/lib/ssg.d.ts +31 -0
  63. package/lib/ssg.js +167 -0
  64. package/lib/templates/templates.d.ts +28 -0
  65. package/lib/templates/templates.js +63 -0
  66. package/lib/utils.d.ts +9 -0
  67. package/lib/utils.js +78 -0
  68. package/lib/webpack/base.d.ts +5 -1
  69. package/lib/webpack/base.js +4 -6
  70. package/lib/webpack/client.d.ts +15 -1
  71. package/lib/webpack/client.js +78 -23
  72. package/lib/webpack/minification.d.ts +8 -0
  73. package/lib/webpack/minification.js +97 -0
  74. package/lib/webpack/server.d.ts +5 -3
  75. package/lib/webpack/server.js +41 -50
  76. package/lib/webpack/utils.d.ts +13 -4
  77. package/lib/webpack/utils.js +27 -83
  78. package/package.json +13 -11
  79. package/lib/commands/start.js +0 -212
  80. package/lib/server/index.js +0 -154
  81. package/lib/server/plugins/index.d.ts +0 -18
  82. package/lib/server/plugins/index.js +0 -106
  83. /package/lib/{webpack/templates/index.html.template.ejs → templates/dev.html.template.ejs} +0 -0
  84. /package/lib/{webpack/templates → templates}/ssr.html.template.d.ts +0 -0
  85. /package/lib/{webpack/templates → templates}/ssr.html.template.js +0 -0
@@ -12,7 +12,7 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
12
12
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
13
13
  const react_router_config_1 = require("react-router-config");
14
14
  const utils_1 = require("@docusaurus/utils");
15
- const utils_2 = require("./utils");
15
+ const utils_common_1 = require("@docusaurus/utils-common");
16
16
  function matchRoutes(routeConfig, pathname) {
17
17
  // @ts-expect-error: React router types RouteConfig with an actual React
18
18
  // component, but we load route components with string paths.
@@ -39,8 +39,8 @@ function createBrokenLinksHelper({ collectedLinks, routes, }) {
39
39
  // We must pre-validate all possible paths
40
40
  validPathnameRoutes.forEach((validPathnameRoute) => {
41
41
  if (!validPathnameRoute.strict) {
42
- validPathnames.add((0, utils_1.addTrailingSlash)(validPathnameRoute.path));
43
- validPathnames.add((0, utils_1.removeTrailingSlash)(validPathnameRoute.path));
42
+ validPathnames.add((0, utils_common_1.addTrailingSlash)(validPathnameRoute.path));
43
+ validPathnames.add((0, utils_common_1.removeTrailingSlash)(validPathnameRoute.path));
44
44
  }
45
45
  });
46
46
  return otherRoutes;
@@ -127,7 +127,7 @@ function getBrokenLinksForPage({ pagePath, helper, }) {
127
127
  */
128
128
  function filterIntermediateRoutes(routesInput) {
129
129
  const routesWithout404 = routesInput.filter((route) => route.path !== '*');
130
- return (0, utils_2.getAllFinalRoutes)(routesWithout404);
130
+ return (0, utils_1.flattenRoutes)(routesWithout404);
131
131
  }
132
132
  function getBrokenLinks({ collectedLinks, routes, }) {
133
133
  const filteredRoutes = filterIntermediateRoutes(routes);
@@ -9,4 +9,4 @@ import type { LoadedPlugin } from '@docusaurus/types';
9
9
  * Runs the `getClientModules` lifecycle. The returned file paths are all
10
10
  * absolute.
11
11
  */
12
- export declare function loadClientModules(plugins: LoadedPlugin[]): string[];
12
+ export declare function getAllClientModules(plugins: LoadedPlugin[]): string[];
@@ -6,15 +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.loadClientModules = void 0;
9
+ exports.getAllClientModules = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const path_1 = tslib_1.__importDefault(require("path"));
12
12
  /**
13
13
  * Runs the `getClientModules` lifecycle. The returned file paths are all
14
14
  * absolute.
15
15
  */
16
- function loadClientModules(plugins) {
16
+ function getAllClientModules(plugins) {
17
17
  return plugins.flatMap((plugin) => plugin.getClientModules?.().map((p) => path_1.default.resolve(plugin.path, p)) ??
18
18
  []);
19
19
  }
20
- exports.loadClientModules = loadClientModules;
20
+ exports.getAllClientModules = getAllClientModules;
@@ -0,0 +1,20 @@
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 { CodeTranslations, DocusaurusConfig, GlobalData, I18n, RouteConfig, SiteMetadata } from '@docusaurus/types';
8
+ type CodegenParams = {
9
+ generatedFilesDir: string;
10
+ siteConfig: DocusaurusConfig;
11
+ baseUrl: string;
12
+ clientModules: string[];
13
+ globalData: GlobalData;
14
+ i18n: I18n;
15
+ codeTranslations: CodeTranslations;
16
+ siteMetadata: SiteMetadata;
17
+ routes: RouteConfig[];
18
+ };
19
+ export declare function generateSiteFiles(params: CodegenParams): Promise<void>;
20
+ export {};
@@ -0,0 +1,65 @@
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.generateSiteFiles = void 0;
10
+ const utils_1 = require("@docusaurus/utils");
11
+ const codegenRoutes_1 = require("./codegenRoutes");
12
+ function genWarning({ generatedFilesDir }) {
13
+ return (0, utils_1.generate)(generatedFilesDir,
14
+ // cSpell:ignore DONT
15
+ 'DONT-EDIT-THIS-FOLDER', `This folder stores temp files that Docusaurus' client bundler accesses.
16
+
17
+ DO NOT hand-modify files in this folder because they will be overwritten in the
18
+ next build. You can clear all build artifacts (including this folder) with the
19
+ \`docusaurus clear\` command.
20
+ `);
21
+ }
22
+ function genSiteConfig({ generatedFilesDir, siteConfig, }) {
23
+ return (0, utils_1.generate)(generatedFilesDir, `${utils_1.DEFAULT_CONFIG_FILE_NAME}.mjs`, `/*
24
+ * AUTOGENERATED - DON'T EDIT
25
+ * Your edits in this file will be overwritten in the next build!
26
+ * Modify the docusaurus.config.js file at your site's root instead.
27
+ */
28
+ export default ${JSON.stringify(siteConfig, null, 2)};
29
+ `);
30
+ }
31
+ function genClientModules({ generatedFilesDir, clientModules, }) {
32
+ return (0, utils_1.generate)(generatedFilesDir, 'client-modules.js', `export default [
33
+ ${clientModules
34
+ // Use `require()` because `import()` is async but client modules can have CSS
35
+ // and the order matters for loading CSS.
36
+ .map((clientModule) => ` require("${(0, utils_1.escapePath)(clientModule)}"),`)
37
+ .join('\n')}
38
+ ];
39
+ `);
40
+ }
41
+ function genGlobalData({ generatedFilesDir, globalData, }) {
42
+ return (0, utils_1.generate)(generatedFilesDir, 'globalData.json', JSON.stringify(globalData, null, 2));
43
+ }
44
+ function genI18n({ generatedFilesDir, i18n, }) {
45
+ return (0, utils_1.generate)(generatedFilesDir, 'i18n.json', JSON.stringify(i18n, null, 2));
46
+ }
47
+ function genCodeTranslations({ generatedFilesDir, codeTranslations, }) {
48
+ return (0, utils_1.generate)(generatedFilesDir, 'codeTranslations.json', JSON.stringify(codeTranslations, null, 2));
49
+ }
50
+ function genSiteMetadata({ generatedFilesDir, siteMetadata, }) {
51
+ return (0, utils_1.generate)(generatedFilesDir, 'site-metadata.json', JSON.stringify(siteMetadata, null, 2));
52
+ }
53
+ async function generateSiteFiles(params) {
54
+ await Promise.all([
55
+ genWarning(params),
56
+ genClientModules(params),
57
+ genSiteConfig(params),
58
+ (0, codegenRoutes_1.generateRouteFiles)(params),
59
+ genGlobalData(params),
60
+ genSiteMetadata(params),
61
+ genI18n(params),
62
+ genCodeTranslations(params),
63
+ ]);
64
+ }
65
+ exports.generateSiteFiles = generateSiteFiles;
@@ -0,0 +1,49 @@
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 { RouteConfig, RouteChunkNames } from '@docusaurus/types';
8
+ type RoutesCode = {
9
+ /** Serialized routes config that can be directly emitted into temp file. */
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
+ /**
22
+ * Generates a unique chunk name that can be used in the chunk registry.
23
+ *
24
+ * @param modulePath A path to generate chunk name from. The actual value has no
25
+ * semantic significance.
26
+ * @param prefix A prefix to append to the chunk name, to avoid name clash.
27
+ * @param preferredName Chunk names default to `modulePath`, and this can supply
28
+ * a more human-readable name.
29
+ * @param shortId When `true`, the chunk name would only be a hash without any
30
+ * other characters. Useful for bundle size. Defaults to `true` in production.
31
+ */
32
+ export declare function genChunkName(modulePath: string, prefix?: string, preferredName?: string, shortId?: boolean): string;
33
+ /**
34
+ * Routes are prepared into three temp files:
35
+ *
36
+ * - `routesConfig`, the route config passed to react-router. This file is kept
37
+ * minimal, because it can't be code-splitted.
38
+ * - `routesChunkNames`, a mapping from route paths (hashed) to code-splitted
39
+ * chunk names.
40
+ * - `registry`, a mapping from chunk names to options for react-loadable.
41
+ */
42
+ export declare function generateRoutesCode(routeConfigs: RouteConfig[]): RoutesCode;
43
+ type GenerateRouteFilesParams = {
44
+ generatedFilesDir: string;
45
+ routes: RouteConfig[];
46
+ baseUrl: string;
47
+ };
48
+ export declare function generateRouteFiles({ generatedFilesDir, routes, }: GenerateRouteFilesParams): Promise<void>;
49
+ export {};
@@ -0,0 +1,190 @@
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.generateRouteFiles = exports.generateRoutesCode = exports.genChunkName = void 0;
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
+ const utils_1 = require("@docusaurus/utils");
14
+ /** Indents every line of `str` by one level. */
15
+ function indent(str) {
16
+ return ` ${str.replace(/\n/g, `\n `)}`;
17
+ }
18
+ const chunkNameCache = new Map();
19
+ const chunkNameCount = 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 = (0, utils_1.docuHash)(str);
44
+ chunkName = prefix ? `${prefix}---${name}` : name;
45
+ }
46
+ const seenCount = (chunkNameCount.get(chunkName) ?? 0) + 1;
47
+ if (seenCount > 1) {
48
+ chunkName += seenCount.toString(36);
49
+ }
50
+ chunkNameCache.set(modulePath, chunkName);
51
+ chunkNameCount.set(chunkName, seenCount);
52
+ }
53
+ return chunkName;
54
+ }
55
+ exports.genChunkName = genChunkName;
56
+ /**
57
+ * Takes a piece of route config, and serializes it into raw JS code. The shape
58
+ * is the same as react-router's `RouteConfig`. Formatting is similar to
59
+ * `JSON.stringify` but without all the quotes.
60
+ */
61
+ function serializeRouteConfig({ routePath, routeHash, exact, subroutesCodeStrings, props, }) {
62
+ const parts = [
63
+ `path: '${routePath}'`,
64
+ `component: ComponentCreator('${routePath}', '${routeHash}')`,
65
+ ];
66
+ if (exact) {
67
+ parts.push(`exact: true`);
68
+ }
69
+ if (subroutesCodeStrings) {
70
+ parts.push(`routes: [
71
+ ${indent(subroutesCodeStrings.join(',\n'))}
72
+ ]`);
73
+ }
74
+ Object.entries(props).forEach(([propName, propValue]) => {
75
+ const isIdentifier = /^[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*$/u.test(propName);
76
+ const key = isIdentifier ? propName : JSON.stringify(propName);
77
+ parts.push(`${key}: ${JSON.stringify(propValue)}`);
78
+ });
79
+ return `{
80
+ ${indent(parts.join(',\n'))}
81
+ }`;
82
+ }
83
+ const isModule = (value) => typeof value === 'string' ||
84
+ (typeof value === 'object' &&
85
+ // eslint-disable-next-line no-underscore-dangle
86
+ !!value?.__import);
87
+ /**
88
+ * Takes a {@link Module} (which is nothing more than a path plus some metadata
89
+ * like query) and returns the string path it represents.
90
+ */
91
+ function getModulePath(target) {
92
+ if (typeof target === 'string') {
93
+ return target;
94
+ }
95
+ const queryStr = target.query ? `?${querystring_1.default.stringify(target.query)}` : '';
96
+ return `${target.path}${queryStr}`;
97
+ }
98
+ function genChunkNames(routeModule, prefix, name, res) {
99
+ if (isModule(routeModule)) {
100
+ // This is a leaf node, no need to recurse
101
+ const modulePath = getModulePath(routeModule);
102
+ const chunkName = genChunkName(modulePath, prefix, name);
103
+ res.registry[chunkName] = (0, utils_1.escapePath)(modulePath);
104
+ return chunkName;
105
+ }
106
+ if (Array.isArray(routeModule)) {
107
+ return routeModule.map((val, index) => genChunkNames(val, `${index}`, name, res));
108
+ }
109
+ return lodash_1.default.mapValues(routeModule, (v, key) => genChunkNames(v, key, name, res));
110
+ }
111
+ /**
112
+ * This is the higher level overview of route code generation. For each route
113
+ * config node, it returns the node's serialized form, and mutates `registry`,
114
+ * `routesPaths`, and `routesChunkNames` accordingly.
115
+ */
116
+ function genRouteCode(routeConfig, res) {
117
+ const { path: routePath, component, modules = {}, context, routes: subroutes, priority, exact, metadata, ...props } = routeConfig;
118
+ if (typeof routePath !== 'string' || !component) {
119
+ throw new Error(`Invalid route config: path must be a string and component is required.
120
+ ${JSON.stringify(routeConfig)}`);
121
+ }
122
+ const routeHash = (0, utils_1.simpleHash)(JSON.stringify(routeConfig), 3);
123
+ res.routesChunkNames[`${routePath}-${routeHash}`] = {
124
+ // Avoid clash with a prop called "component"
125
+ ...genChunkNames({ __comp: component }, 'component', component, res),
126
+ ...(context &&
127
+ genChunkNames({ __context: context }, 'context', routePath, res)),
128
+ ...genChunkNames(modules, 'module', routePath, res),
129
+ };
130
+ return serializeRouteConfig({
131
+ routePath: routePath.replace(/'/g, "\\'"),
132
+ routeHash,
133
+ subroutesCodeStrings: subroutes?.map((r) => genRouteCode(r, res)),
134
+ exact,
135
+ props,
136
+ });
137
+ }
138
+ /**
139
+ * Routes are prepared into three temp files:
140
+ *
141
+ * - `routesConfig`, the route config passed to react-router. This file is kept
142
+ * minimal, because it can't be code-splitted.
143
+ * - `routesChunkNames`, a mapping from route paths (hashed) to code-splitted
144
+ * chunk names.
145
+ * - `registry`, a mapping from chunk names to options for react-loadable.
146
+ */
147
+ function generateRoutesCode(routeConfigs) {
148
+ const res = {
149
+ // To be written by `genRouteCode`
150
+ routesConfig: '',
151
+ routesChunkNames: {},
152
+ registry: {},
153
+ };
154
+ // `genRouteCode` would mutate `res`
155
+ const routeConfigSerialized = routeConfigs
156
+ .map((r) => genRouteCode(r, res))
157
+ .join(',\n');
158
+ res.routesConfig = `import React from 'react';
159
+ import ComponentCreator from '@docusaurus/ComponentCreator';
160
+
161
+ export default [
162
+ ${indent(routeConfigSerialized)},
163
+ {
164
+ path: '*',
165
+ component: ComponentCreator('*'),
166
+ },
167
+ ];
168
+ `;
169
+ return res;
170
+ }
171
+ exports.generateRoutesCode = generateRoutesCode;
172
+ const genRegistry = ({ generatedFilesDir, registry, }) => (0, utils_1.generate)(generatedFilesDir, 'registry.js', `export default {
173
+ ${Object.entries(registry)
174
+ .sort((a, b) => a[0].localeCompare(b[0]))
175
+ .map(([chunkName, modulePath]) =>
176
+ // modulePath is already escaped by escapePath
177
+ ` "${chunkName}": [() => import(/* webpackChunkName: "${chunkName}" */ "${modulePath}"), "${modulePath}", require.resolveWeak("${modulePath}")],`)
178
+ .join('\n')}};
179
+ `);
180
+ const genRoutesChunkNames = ({ generatedFilesDir, routesChunkNames, }) => (0, utils_1.generate)(generatedFilesDir, 'routesChunkNames.json', JSON.stringify(routesChunkNames, null, 2));
181
+ const genRoutes = ({ generatedFilesDir, routesConfig, }) => (0, utils_1.generate)(generatedFilesDir, 'routes.js', routesConfig);
182
+ async function generateRouteFiles({ generatedFilesDir, routes, }) {
183
+ const { registry, routesChunkNames, routesConfig } = generateRoutesCode(routes);
184
+ await Promise.all([
185
+ genRegistry({ generatedFilesDir, registry }),
186
+ genRoutesChunkNames({ generatedFilesDir, routesChunkNames }),
187
+ genRoutes({ generatedFilesDir, routesConfig }),
188
+ ]);
189
+ }
190
+ exports.generateRouteFiles = generateRouteFiles;
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.validateConfig = exports.ConfigSchema = exports.DEFAULT_CONFIG = exports.DEFAULT_MARKDOWN_CONFIG = exports.DEFAULT_I18N_CONFIG = void 0;
10
10
  const utils_1 = require("@docusaurus/utils");
11
11
  const utils_validation_1 = require("@docusaurus/utils-validation");
12
+ const utils_common_1 = require("@docusaurus/utils-common");
12
13
  const DEFAULT_I18N_LOCALE = 'en';
13
14
  exports.DEFAULT_I18N_CONFIG = {
14
15
  defaultLocale: DEFAULT_I18N_LOCALE,
@@ -51,12 +52,13 @@ exports.DEFAULT_CONFIG = {
51
52
  markdown: exports.DEFAULT_MARKDOWN_CONFIG,
52
53
  };
53
54
  function createPluginSchema(theme) {
54
- return utils_validation_1.Joi.alternatives()
55
+ return (utils_validation_1.Joi.alternatives()
55
56
  .try(utils_validation_1.Joi.function(), utils_validation_1.Joi.array()
56
57
  .ordered(utils_validation_1.Joi.function().required(), utils_validation_1.Joi.object().required())
57
58
  .length(2), utils_validation_1.Joi.string(), utils_validation_1.Joi.array()
58
59
  .ordered(utils_validation_1.Joi.string().required(), utils_validation_1.Joi.object().required())
59
60
  .length(2), utils_validation_1.Joi.any().valid(false, null))
61
+ // @ts-expect-error: bad lib def, doesn't recognize an array of reports
60
62
  .error((errors) => {
61
63
  errors.forEach((error) => {
62
64
  const validConfigExample = theme
@@ -85,7 +87,7 @@ ${validConfigExample}
85
87
  `;
86
88
  });
87
89
  return errors;
88
- });
90
+ }));
89
91
  }
90
92
  const PluginSchema = createPluginSchema(false);
91
93
  const ThemeSchema = createPluginSchema(true);
@@ -127,7 +129,7 @@ const SiteUrlSchema = utils_validation_1.Joi.string()
127
129
  catch {
128
130
  return helpers.error('any.invalid');
129
131
  }
130
- return (0, utils_1.removeTrailingSlash)(value);
132
+ return (0, utils_common_1.removeTrailingSlash)(value);
131
133
  })
132
134
  .messages({
133
135
  'any.invalid': '"{#value}" does not look like a valid URL. Make sure it has a protocol; for example, "https://example.com".',
@@ -140,7 +142,7 @@ exports.ConfigSchema = utils_validation_1.Joi.object({
140
142
  .alternatives()
141
143
  .try(utils_validation_1.Joi.string().required().allow(''))
142
144
  .required()
143
- .custom((value) => (0, utils_1.addLeadingSlash)((0, utils_1.addTrailingSlash)(value))),
145
+ .custom((value) => (0, utils_common_1.addLeadingSlash)((0, utils_common_1.addTrailingSlash)(value))),
144
146
  baseUrlIssueBanner: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.baseUrlIssueBanner),
145
147
  favicon: utils_validation_1.Joi.string().optional(),
146
148
  title: utils_validation_1.Joi.string().required(),
@@ -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 { LoadContextOptions } from './index';
8
+ import type { LoadContextParams } from './site';
9
9
  export declare function getDefaultLocaleConfig(locale: string): I18nLocaleConfig;
10
- export declare function loadI18n(config: DocusaurusConfig, options: Pick<LoadContextOptions, 'locale'>): Promise<I18n>;
10
+ export declare function loadI18n(config: DocusaurusConfig, options: Pick<LoadContextParams, 'locale'>): Promise<I18n>;
@@ -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
- // If the locale name includes -u-ca-xxx the calendar will be defined
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 doGetPluginVersion(normalizedPluginConfig) {
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.getPluginVersion)(pluginPath, context.siteDir);
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 doGetPluginVersion(normalizedPluginConfig);
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>;