@docusaurus/core 2.0.0-beta.17 → 2.0.0-beta.18

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 (94) hide show
  1. package/bin/beforeCli.mjs +2 -5
  2. package/bin/docusaurus.mjs +20 -21
  3. package/lib/choosePort.js +3 -6
  4. package/lib/client/App.js +6 -2
  5. package/lib/client/LinksCollector.d.ts +1 -1
  6. package/lib/client/LinksCollector.js +3 -3
  7. package/lib/client/SiteMetadataDefaults.d.ts +8 -0
  8. package/lib/client/SiteMetadataDefaults.js +19 -0
  9. package/lib/client/{exports/browserContext.d.ts → browserContext.d.ts} +0 -0
  10. package/lib/client/{exports/browserContext.js → browserContext.js} +0 -0
  11. package/lib/client/clientEntry.js +2 -2
  12. package/lib/client/{exports/docusaurusContext.d.ts → docusaurusContext.d.ts} +0 -0
  13. package/lib/client/{exports/docusaurusContext.js → docusaurusContext.js} +0 -0
  14. package/lib/client/exports/BrowserOnly.js +1 -1
  15. package/lib/client/exports/ComponentCreator.js +34 -14
  16. package/lib/client/exports/Interpolate.d.ts +1 -1
  17. package/lib/client/exports/Interpolate.js +4 -4
  18. package/lib/client/exports/Link.d.ts +1 -1
  19. package/lib/client/exports/Link.js +1 -1
  20. package/lib/client/exports/Translate.d.ts +2 -2
  21. package/lib/client/exports/Translate.js +2 -1
  22. package/lib/client/exports/useBaseUrl.js +5 -0
  23. package/lib/client/exports/useDocusaurusContext.js +1 -1
  24. package/lib/client/exports/useGlobalData.d.ts +4 -3
  25. package/lib/client/exports/useIsBrowser.js +1 -1
  26. package/lib/client/exports/useRouteContext.d.ts +8 -0
  27. package/lib/client/exports/useRouteContext.js +15 -0
  28. package/lib/client/flat.d.ts +3 -1
  29. package/lib/client/flat.js +1 -2
  30. package/lib/client/normalizeLocation.js +1 -5
  31. package/lib/client/prefetch.js +3 -3
  32. package/lib/client/preload.js +3 -9
  33. package/lib/client/routeContext.d.ts +13 -0
  34. package/lib/client/routeContext.js +31 -0
  35. package/lib/client/serverEntry.js +7 -7
  36. package/lib/client/theme-fallback/Error/index.js +5 -1
  37. package/lib/client/theme-fallback/Layout/index.d.ts +1 -1
  38. package/lib/client/theme-fallback/Layout/index.js +2 -17
  39. package/lib/client/theme-fallback/NotFound/index.js +11 -5
  40. package/lib/client/theme-fallback/Root/index.d.ts +4 -4
  41. package/lib/client/theme-fallback/Root/index.js +2 -1
  42. package/lib/client/theme-fallback/SiteMetadata/index.d.ts +8 -0
  43. package/lib/client/theme-fallback/SiteMetadata/index.js +10 -0
  44. package/lib/commands/build.js +1 -1
  45. package/lib/commands/commandUtils.js +1 -1
  46. package/lib/commands/deploy.d.ts +0 -3
  47. package/lib/commands/deploy.js +4 -31
  48. package/lib/commands/external.js +1 -5
  49. package/lib/commands/start.js +7 -8
  50. package/lib/commands/swizzle/actions.js +1 -2
  51. package/lib/commands/swizzle/context.js +1 -3
  52. package/lib/commands/swizzle/tables.js +7 -10
  53. package/lib/commands/swizzle/themes.js +5 -2
  54. package/lib/commands/writeHeadingIds.d.ts +2 -9
  55. package/lib/commands/writeHeadingIds.js +2 -57
  56. package/lib/server/brokenLinks.d.ts +3 -16
  57. package/lib/server/brokenLinks.js +12 -19
  58. package/lib/server/client-modules/index.d.ts +2 -2
  59. package/lib/server/client-modules/index.js +4 -1
  60. package/lib/server/config.js +1 -1
  61. package/lib/server/configValidation.d.ts +1 -1
  62. package/lib/server/configValidation.js +34 -9
  63. package/lib/server/duplicateRoutes.d.ts +0 -2
  64. package/lib/server/duplicateRoutes.js +8 -8
  65. package/lib/server/html-tags/htmlTags.js +1 -1
  66. package/lib/server/html-tags/index.d.ts +1 -2
  67. package/lib/server/html-tags/index.js +2 -3
  68. package/lib/server/i18n.d.ts +1 -1
  69. package/lib/server/i18n.js +2 -9
  70. package/lib/server/index.js +36 -31
  71. package/lib/server/plugins/index.d.ts +2 -2
  72. package/lib/server/plugins/index.js +25 -12
  73. package/lib/server/plugins/init.d.ts +6 -2
  74. package/lib/server/plugins/init.js +34 -37
  75. package/lib/server/presets/index.js +7 -13
  76. package/lib/server/routes.d.ts +2 -4
  77. package/lib/server/routes.js +23 -12
  78. package/lib/server/themes/alias.js +3 -1
  79. package/lib/server/themes/index.js +4 -4
  80. package/lib/server/translations/translations.d.ts +12 -13
  81. package/lib/server/translations/translations.js +4 -10
  82. package/lib/server/translations/translationsExtractor.d.ts +3 -1
  83. package/lib/server/translations/translationsExtractor.js +3 -4
  84. package/lib/server/versions/index.d.ts +2 -2
  85. package/lib/server/versions/index.js +2 -5
  86. package/lib/webpack/base.d.ts +3 -1
  87. package/lib/webpack/plugins/ChunkAssetPlugin.js +7 -7
  88. package/lib/webpack/plugins/CleanWebpackPlugin.js +1 -1
  89. package/lib/webpack/utils.d.ts +6 -0
  90. package/lib/webpack/utils.js +1 -3
  91. package/package.json +26 -26
  92. package/lib/server/versions/__fixtures__/dummy-plugin.d.ts +0 -0
  93. package/lib/server/versions/__fixtures__/dummy-plugin.js +0 -0
  94. package/lib/server/versions/__fixtures__/package.json +0 -3
@@ -4,5 +4,5 @@
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 { Plugin } from '@docusaurus/types';
8
- export default function loadClientModules(plugins: Plugin<unknown>[]): string[];
7
+ import type { LoadedPlugin } from '@docusaurus/types';
8
+ export default function loadClientModules(plugins: LoadedPlugin<unknown>[]): string[];
@@ -6,7 +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
+ const tslib_1 = require("tslib");
10
+ const path_1 = tslib_1.__importDefault(require("path"));
9
11
  function loadClientModules(plugins) {
10
- return plugins.flatMap((plugin) => plugin.getClientModules?.() ?? []);
12
+ return plugins.flatMap((plugin) => plugin.getClientModules?.().map((p) => path_1.default.resolve(plugin.path, p)) ??
13
+ []);
11
14
  }
12
15
  exports.default = loadClientModules;
@@ -15,7 +15,7 @@ async function loadConfig(configPath) {
15
15
  throw new Error(`Config file at "${configPath}" not found.`);
16
16
  }
17
17
  const importedConfig = (0, import_fresh_1.default)(configPath);
18
- const loadedConfig = importedConfig instanceof Function
18
+ const loadedConfig = typeof importedConfig === 'function'
19
19
  ? await importedConfig()
20
20
  : await importedConfig;
21
21
  return (0, configValidation_1.validateConfig)(loadedConfig);
@@ -7,6 +7,6 @@
7
7
  import type { DocusaurusConfig, I18nConfig } from '@docusaurus/types';
8
8
  import { Joi } from '@docusaurus/utils-validation';
9
9
  export declare const DEFAULT_I18N_CONFIG: I18nConfig;
10
- export declare const DEFAULT_CONFIG: Pick<DocusaurusConfig, 'i18n' | 'onBrokenLinks' | 'onBrokenMarkdownLinks' | 'onDuplicateRoutes' | 'plugins' | 'themes' | 'presets' | 'customFields' | 'themeConfig' | 'titleDelimiter' | 'noIndex' | 'tagline' | 'baseUrlIssueBanner' | 'staticDirectories'>;
10
+ export declare const DEFAULT_CONFIG: Pick<DocusaurusConfig, 'i18n' | 'onBrokenLinks' | 'onBrokenMarkdownLinks' | 'onDuplicateRoutes' | 'plugins' | 'themes' | 'presets' | 'stylesheets' | 'scripts' | 'clientModules' | 'customFields' | 'themeConfig' | 'titleDelimiter' | 'noIndex' | 'tagline' | 'baseUrlIssueBanner' | 'staticDirectories'>;
11
11
  export declare const ConfigSchema: Joi.ObjectSchema<any>;
12
12
  export declare function validateConfig(config: Partial<DocusaurusConfig>): DocusaurusConfig;
@@ -23,17 +23,22 @@ exports.DEFAULT_CONFIG = {
23
23
  plugins: [],
24
24
  themes: [],
25
25
  presets: [],
26
+ stylesheets: [],
27
+ scripts: [],
28
+ clientModules: [],
26
29
  customFields: {},
27
30
  themeConfig: {},
28
31
  titleDelimiter: '|',
29
32
  noIndex: false,
30
33
  tagline: '',
31
34
  baseUrlIssueBanner: true,
32
- staticDirectories: [utils_1.STATIC_DIR_NAME],
35
+ staticDirectories: [utils_1.DEFAULT_STATIC_DIR_NAME],
33
36
  };
34
- function createPluginSchema(theme = false) {
37
+ function createPluginSchema(theme) {
35
38
  return (utils_validation_1.Joi.alternatives()
36
- .try(utils_validation_1.Joi.function(), utils_validation_1.Joi.array().ordered(utils_validation_1.Joi.function().required(), utils_validation_1.Joi.object().required()), utils_validation_1.Joi.string(), utils_validation_1.Joi.array()
39
+ .try(utils_validation_1.Joi.function(), utils_validation_1.Joi.array()
40
+ .ordered(utils_validation_1.Joi.function().required(), utils_validation_1.Joi.object().required())
41
+ .length(2), utils_validation_1.Joi.string(), utils_validation_1.Joi.array()
37
42
  .ordered(utils_validation_1.Joi.string().required(), utils_validation_1.Joi.object().required())
38
43
  .length(2), utils_validation_1.Joi.bool().equal(false))
39
44
  // @ts-expect-error: bad lib def, doesn't recognize an array of reports
@@ -69,7 +74,15 @@ ${validConfigExample}
69
74
  }
70
75
  const PluginSchema = createPluginSchema(false);
71
76
  const ThemeSchema = createPluginSchema(true);
72
- const PresetSchema = utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.string(), utils_validation_1.Joi.array().items(utils_validation_1.Joi.string().required(), utils_validation_1.Joi.object().required()).length(2));
77
+ const PresetSchema = utils_validation_1.Joi.alternatives()
78
+ .try(utils_validation_1.Joi.string(), utils_validation_1.Joi.array()
79
+ .items(utils_validation_1.Joi.string().required(), utils_validation_1.Joi.object().required())
80
+ .length(2))
81
+ .messages({
82
+ 'alternatives.types': `{#label} does not look like a valid preset config. A preset config entry should be one of:
83
+ - A tuple of [presetName, options], like \`["classic", \\{ blog: false \\}]\`, or
84
+ - A simple string, like \`"classic"\``,
85
+ });
73
86
  const LocaleConfigSchema = utils_validation_1.Joi.object({
74
87
  label: utils_validation_1.Joi.string(),
75
88
  htmlLang: utils_validation_1.Joi.string(),
@@ -129,19 +142,31 @@ exports.ConfigSchema = utils_validation_1.Joi.object({
129
142
  themes: utils_validation_1.Joi.array().items(ThemeSchema).default(exports.DEFAULT_CONFIG.themes),
130
143
  presets: utils_validation_1.Joi.array().items(PresetSchema).default(exports.DEFAULT_CONFIG.presets),
131
144
  themeConfig: utils_validation_1.Joi.object().unknown().default(exports.DEFAULT_CONFIG.themeConfig),
132
- scripts: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
145
+ scripts: utils_validation_1.Joi.array()
146
+ .items(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
133
147
  src: utils_validation_1.Joi.string().required(),
134
148
  async: utils_validation_1.Joi.bool(),
135
149
  defer: utils_validation_1.Joi.bool(),
136
150
  })
137
151
  // See https://github.com/facebook/docusaurus/issues/3378
138
- .unknown()),
152
+ .unknown())
153
+ .messages({
154
+ 'array.includes': '{#label} is invalid. A script must be a plain string (the src), or an object with at least a "src" property.',
155
+ })
156
+ .default(exports.DEFAULT_CONFIG.scripts),
139
157
  ssrTemplate: utils_validation_1.Joi.string(),
140
- stylesheets: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
158
+ stylesheets: utils_validation_1.Joi.array()
159
+ .items(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
141
160
  href: utils_validation_1.Joi.string().required(),
142
161
  type: utils_validation_1.Joi.string(),
143
- }).unknown()),
144
- clientModules: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()),
162
+ }).unknown())
163
+ .messages({
164
+ 'array.includes': '{#label} is invalid. A stylesheet must be a plain string (the href), or an object with at least a "href" property.',
165
+ })
166
+ .default(exports.DEFAULT_CONFIG.stylesheets),
167
+ clientModules: utils_validation_1.Joi.array()
168
+ .items(utils_validation_1.Joi.string())
169
+ .default(exports.DEFAULT_CONFIG.clientModules),
145
170
  tagline: utils_validation_1.Joi.string().allow('').default(exports.DEFAULT_CONFIG.tagline),
146
171
  titleDelimiter: utils_validation_1.Joi.string().default('|'),
147
172
  noIndex: utils_validation_1.Joi.bool().default(false),
@@ -5,6 +5,4 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { ReportingSeverity, RouteConfig } from '@docusaurus/types';
8
- export declare function getAllDuplicateRoutes(pluginsRouteConfigs: RouteConfig[]): string[];
9
- export declare function getDuplicateRoutesMessage(allDuplicateRoutes: string[]): string;
10
8
  export declare function handleDuplicateRoutes(pluginsRouteConfigs: RouteConfig[], onDuplicateRoutes: ReportingSeverity): void;
@@ -6,28 +6,26 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.handleDuplicateRoutes = exports.getDuplicateRoutesMessage = exports.getAllDuplicateRoutes = void 0;
9
+ exports.handleDuplicateRoutes = void 0;
10
10
  const utils_1 = require("@docusaurus/utils");
11
11
  const utils_2 = require("./utils");
12
12
  function getAllDuplicateRoutes(pluginsRouteConfigs) {
13
13
  const allRoutes = (0, utils_2.getAllFinalRoutes)(pluginsRouteConfigs).map((routeConfig) => routeConfig.path);
14
- const seenRoutes = {};
14
+ const seenRoutes = new Set();
15
15
  return allRoutes.filter((route) => {
16
- if (Object.prototype.hasOwnProperty.call(seenRoutes, route)) {
16
+ if (seenRoutes.has(route)) {
17
17
  return true;
18
18
  }
19
- seenRoutes[route] = true;
19
+ seenRoutes.add(route);
20
20
  return false;
21
21
  });
22
22
  }
23
- exports.getAllDuplicateRoutes = getAllDuplicateRoutes;
24
23
  function getDuplicateRoutesMessage(allDuplicateRoutes) {
25
24
  const message = allDuplicateRoutes
26
- .map((duplicateRoute) => `Attempting to create page at ${duplicateRoute}, but a page already exists at this route`)
25
+ .map((duplicateRoute) => `- Attempting to create page at ${duplicateRoute}, but a page already exists at this route.`)
27
26
  .join('\n');
28
27
  return message;
29
28
  }
30
- exports.getDuplicateRoutesMessage = getDuplicateRoutesMessage;
31
29
  function handleDuplicateRoutes(pluginsRouteConfigs, onDuplicateRoutes) {
32
30
  if (onDuplicateRoutes === 'ignore') {
33
31
  return;
@@ -35,7 +33,9 @@ function handleDuplicateRoutes(pluginsRouteConfigs, onDuplicateRoutes) {
35
33
  const duplicatePaths = getAllDuplicateRoutes(pluginsRouteConfigs);
36
34
  const message = getDuplicateRoutesMessage(duplicatePaths);
37
35
  if (message) {
38
- const finalMessage = `Duplicate routes found!\n${message}\nThis could lead to non-deterministic routing behavior`;
36
+ const finalMessage = `Duplicate routes found!
37
+ ${message}
38
+ This could lead to non-deterministic routing behavior.`;
39
39
  (0, utils_1.reportMessage)(finalMessage, onDuplicateRoutes);
40
40
  }
41
41
  }
@@ -24,7 +24,7 @@ function htmlTagObjectToString(tagDefinition) {
24
24
  throw new Error(`Error loading ${JSON.stringify(tagDefinition)}, "${tagDefinition.tagName}" is not a valid HTML tags.`);
25
25
  }
26
26
  const isVoidTag = void_1.default.indexOf(tagDefinition.tagName) !== -1;
27
- const tagAttributes = tagDefinition.attributes || {};
27
+ const tagAttributes = tagDefinition.attributes ?? {};
28
28
  const attributes = Object.keys(tagAttributes)
29
29
  .filter((attributeName) => tagAttributes[attributeName] !== false)
30
30
  .map((attributeName) => {
@@ -4,6 +4,5 @@
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 { InjectedHtmlTags, HtmlTags, LoadedPlugin } from '@docusaurus/types';
8
- export declare function createHtmlTagsString(tags: HtmlTags): string;
7
+ import type { InjectedHtmlTags, LoadedPlugin } from '@docusaurus/types';
9
8
  export declare function loadHtmlTags(plugins: LoadedPlugin[]): InjectedHtmlTags;
@@ -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.loadHtmlTags = exports.createHtmlTagsString = void 0;
9
+ exports.loadHtmlTags = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const htmlTags_1 = tslib_1.__importDefault(require("./htmlTags"));
12
12
  function toString(val) {
@@ -15,13 +15,12 @@ function toString(val) {
15
15
  function createHtmlTagsString(tags) {
16
16
  return Array.isArray(tags) ? tags.map(toString).join('\n') : toString(tags);
17
17
  }
18
- exports.createHtmlTagsString = createHtmlTagsString;
19
18
  function loadHtmlTags(plugins) {
20
19
  const htmlTags = plugins.reduce((acc, plugin) => {
21
20
  if (!plugin.injectHtmlTags) {
22
21
  return acc;
23
22
  }
24
- const { headTags, preBodyTags, postBodyTags } = plugin.injectHtmlTags({ content: plugin.content }) || {};
23
+ const { headTags, preBodyTags, postBodyTags } = plugin.injectHtmlTags({ content: plugin.content }) ?? {};
25
24
  return {
26
25
  headTags: headTags
27
26
  ? `${acc.headTags}\n${createHtmlTagsString(headTags)}`
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import type { I18n, DocusaurusConfig, I18nLocaleConfig } from '@docusaurus/types';
8
8
  export declare function getDefaultLocaleConfig(locale: string): I18nLocaleConfig;
9
- export declare function loadI18n(config: DocusaurusConfig, options?: {
9
+ export declare function loadI18n(config: DocusaurusConfig, options: {
10
10
  locale?: string;
11
11
  }): Promise<I18n>;
12
12
  export declare function localizePath({ pathType, path: originalPath, i18n, options, }: {
@@ -14,9 +14,6 @@ const rtl_detect_1 = require("rtl-detect");
14
14
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
15
15
  function getDefaultLocaleLabel(locale) {
16
16
  const languageName = new Intl.DisplayNames(locale, { type: 'language' }).of(locale);
17
- if (!languageName) {
18
- return locale;
19
- }
20
17
  return (languageName.charAt(0).toLocaleUpperCase(locale) + languageName.substring(1));
21
18
  }
22
19
  function getDefaultLocaleConfig(locale) {
@@ -27,7 +24,7 @@ function getDefaultLocaleConfig(locale) {
27
24
  };
28
25
  }
29
26
  exports.getDefaultLocaleConfig = getDefaultLocaleConfig;
30
- async function loadI18n(config, options = {}) {
27
+ async function loadI18n(config, options) {
31
28
  const { i18n: i18nConfig } = config;
32
29
  const currentLocale = options.locale ?? i18nConfig.defaultLocale;
33
30
  if (!i18nConfig.locales.includes(currentLocale)) {
@@ -64,10 +61,6 @@ function localizePath({ pathType, path: originalPath, i18n, options = {}, }) {
64
61
  return path_1.default.join(originalPath, i18n.currentLocale);
65
62
  }
66
63
  // Url paths; add a trailing slash so it's a valid base URL
67
- if (pathType === 'url') {
68
- return (0, utils_1.normalizeUrl)([originalPath, i18n.currentLocale, '/']);
69
- }
70
- // should never happen
71
- throw new Error(`Unhandled path type "${pathType}".`);
64
+ return (0, utils_1.normalizeUrl)([originalPath, i18n.currentLocale, '/']);
72
65
  }
73
66
  exports.localizePath = localizePath;
@@ -27,27 +27,20 @@ const remark_admonitions_1 = tslib_1.__importDefault(require("remark-admonitions
27
27
  const module_1 = require("module");
28
28
  const moduleShorthand_1 = require("./moduleShorthand");
29
29
  async function loadSiteConfig({ siteDir, customConfigFilePath, }) {
30
- const siteConfigPathUnresolved = customConfigFilePath ?? utils_1.DEFAULT_CONFIG_FILE_NAME;
31
- const siteConfigPath = path_1.default.isAbsolute(siteConfigPathUnresolved)
32
- ? siteConfigPathUnresolved
33
- : path_1.default.resolve(siteDir, siteConfigPathUnresolved);
30
+ const siteConfigPath = path_1.default.resolve(siteDir, customConfigFilePath ?? utils_1.DEFAULT_CONFIG_FILE_NAME);
34
31
  const siteConfig = await (0, config_1.default)(siteConfigPath);
35
32
  return { siteConfig, siteConfigPath };
36
33
  }
37
34
  exports.loadSiteConfig = loadSiteConfig;
38
35
  async function loadContext(siteDir, options = {}) {
39
36
  const { customOutDir, locale, customConfigFilePath } = options;
40
- const generatedFilesDir = path_1.default.isAbsolute(utils_1.GENERATED_FILES_DIR_NAME)
41
- ? utils_1.GENERATED_FILES_DIR_NAME
42
- : path_1.default.resolve(siteDir, utils_1.GENERATED_FILES_DIR_NAME);
37
+ const generatedFilesDir = path_1.default.resolve(siteDir, utils_1.GENERATED_FILES_DIR_NAME);
43
38
  const { siteConfig: initialSiteConfig, siteConfigPath } = await loadSiteConfig({
44
39
  siteDir,
45
40
  customConfigFilePath,
46
41
  });
47
42
  const { ssrTemplate } = initialSiteConfig;
48
- const baseOutDir = customOutDir
49
- ? path_1.default.resolve(customOutDir)
50
- : path_1.default.resolve(siteDir, utils_1.DEFAULT_BUILD_DIR_NAME);
43
+ const baseOutDir = path_1.default.resolve(siteDir, customOutDir ?? utils_1.DEFAULT_BUILD_DIR_NAME);
51
44
  const i18n = await (0, i18n_1.loadI18n)(initialSiteConfig, { locale });
52
45
  const baseUrl = (0, i18n_1.localizePath)({
53
46
  path: initialSiteConfig.baseUrl,
@@ -100,8 +93,8 @@ async function loadPluginConfigs(context) {
100
93
  }
101
94
  presetPlugins = presetPlugins.map((plugin) => normalizeShorthand(plugin, 'plugin'));
102
95
  presetThemes = presetThemes.map((theme) => normalizeShorthand(theme, 'theme'));
103
- const standalonePlugins = (siteConfig.plugins || []).map((plugin) => normalizeShorthand(plugin, 'plugin'));
104
- const standaloneThemes = (siteConfig.themes || []).map((theme) => normalizeShorthand(theme, 'theme'));
96
+ const standalonePlugins = siteConfig.plugins.map((plugin) => normalizeShorthand(plugin, 'plugin'));
97
+ const standaloneThemes = siteConfig.themes.map((theme) => normalizeShorthand(theme, 'theme'));
105
98
  return [
106
99
  ...presetPlugins,
107
100
  ...presetThemes,
@@ -114,13 +107,16 @@ exports.loadPluginConfigs = loadPluginConfigs;
114
107
  // Make a fake plugin to:
115
108
  // - Resolve aliased theme components
116
109
  // - Inject scripts/stylesheets
117
- function createBootstrapPlugin({ siteConfig, }) {
118
- const { stylesheets = [], scripts = [], clientModules: siteConfigClientModules = [], } = siteConfig;
110
+ function createBootstrapPlugin({ siteDir, siteConfig, }) {
111
+ const { stylesheets, scripts, clientModules: siteConfigClientModules, } = siteConfig;
119
112
  return {
120
113
  name: 'docusaurus-bootstrap-plugin',
121
114
  content: null,
122
- options: {},
115
+ options: {
116
+ id: 'default',
117
+ },
123
118
  version: { type: 'synthetic' },
119
+ path: siteDir,
124
120
  getClientModules() {
125
121
  return siteConfigClientModules;
126
122
  },
@@ -158,8 +154,12 @@ function createMDXFallbackPlugin({ siteDir, siteConfig, }) {
158
154
  return {
159
155
  name: 'docusaurus-mdx-fallback-plugin',
160
156
  content: null,
161
- options: {},
157
+ options: {
158
+ id: 'default',
159
+ },
162
160
  version: { type: 'synthetic' },
161
+ // Synthetic, the path doesn't matter much
162
+ path: '.',
163
163
  configureWebpack(config, isServer, { getJSLoader }) {
164
164
  // We need the mdx fallback loader to exclude files that were already
165
165
  // processed by content plugins mdx loaders. This works, but a bit
@@ -184,7 +184,7 @@ function createMDXFallbackPlugin({ siteDir, siteConfig, }) {
184
184
  options: {
185
185
  staticDirs: siteConfig.staticDirectories.map((dir) => path_1.default.resolve(siteDir, dir)),
186
186
  siteDir,
187
- isMDXPartial: (_filename) => true,
187
+ isMDXPartial: () => true,
188
188
  isMDXPartialFrontMatterWarningDisabled: true,
189
189
  remarkPlugins: [remark_admonitions_1.default],
190
190
  },
@@ -208,6 +208,7 @@ async function load(siteDir, options = {}) {
208
208
  context.siteConfig.themeConfig = themeConfigTranslated;
209
209
  (0, duplicateRoutes_1.handleDuplicateRoutes)(pluginsRouteConfigs, siteConfig.onDuplicateRoutes);
210
210
  const genWarning = (0, utils_1.generate)(generatedFilesDir, 'DONT-EDIT-THIS-FOLDER', `This folder stores temp files that Docusaurus' client bundler accesses.
211
+
211
212
  DO NOT hand-modify files in this folder because they will be overwritten in the
212
213
  next build. You can clear all build artifacts (including this folder) with the
213
214
  \`docusaurus clear\` command.
@@ -215,29 +216,33 @@ next build. You can clear all build artifacts (including this folder) with the
215
216
  // Site config must be generated after plugins
216
217
  // We want the generated config to have been normalized by the plugins!
217
218
  const genSiteConfig = (0, utils_1.generate)(generatedFilesDir, utils_1.DEFAULT_CONFIG_FILE_NAME, `/*
218
- AUTOGENERATED - DON'T EDIT
219
- Your edits in this file will be overwritten in the next build!
220
- Modify the docusaurus.config.js file at your site's root instead.
221
- */
222
- export default ${JSON.stringify(siteConfig, null, 2)};`);
223
- plugins.push(createBootstrapPlugin({ siteConfig }));
224
- plugins.push(createMDXFallbackPlugin({ siteDir, siteConfig }));
219
+ * AUTOGENERATED - DON'T EDIT
220
+ * Your edits in this file will be overwritten in the next build!
221
+ * Modify the docusaurus.config.js file at your site's root instead.
222
+ */
223
+ export default ${JSON.stringify(siteConfig, null, 2)};
224
+ `);
225
+ plugins.push(createBootstrapPlugin({ siteDir, siteConfig }), createMDXFallbackPlugin({ siteDir, siteConfig }));
225
226
  // Load client modules.
226
227
  const clientModules = (0, client_modules_1.default)(plugins);
227
- const genClientModules = (0, utils_1.generate)(generatedFilesDir, 'client-modules.js', `export default [\n${clientModules
228
+ const genClientModules = (0, utils_1.generate)(generatedFilesDir, 'client-modules.js', `export default [
229
+ ${clientModules
228
230
  // import() is async so we use require() because client modules can have
229
231
  // CSS and the order matters for loading CSS.
230
232
  .map((module) => ` require('${(0, utils_1.escapePath)(module)}'),`)
231
- .join('\n')}\n];\n`);
233
+ .join('\n')}
234
+ ];
235
+ `);
232
236
  // Load extra head & body html tags.
233
237
  const { headTags, preBodyTags, postBodyTags } = (0, html_tags_1.loadHtmlTags)(plugins);
234
238
  // Routing.
235
239
  const { registry, routesChunkNames, routesConfig, routesPaths } = await (0, routes_1.default)(pluginsRouteConfigs, baseUrl);
236
240
  const genRegistry = (0, utils_1.generate)(generatedFilesDir, 'registry.js', `export default {
237
- ${Object.keys(registry)
238
- .sort()
239
- .map((key) => ` '${key}': [${registry[key].loader}, '${(0, utils_1.escapePath)(registry[key].modulePath)}', require.resolveWeak('${(0, utils_1.escapePath)(registry[key].modulePath)}')],`)
240
- .join('\n')}};\n`);
241
+ ${Object.entries(registry)
242
+ .sort((a, b) => a[0].localeCompare(b[0]))
243
+ .map(([key, chunk]) => ` '${key}': [${chunk.loader}, '${(0, utils_1.escapePath)(chunk.modulePath)}', require.resolveWeak('${(0, utils_1.escapePath)(chunk.modulePath)}')],`)
244
+ .join('\n')}};
245
+ `);
241
246
  const genRoutesChunkNames = (0, utils_1.generate)(generatedFilesDir, 'routesChunkNames.json', JSON.stringify(routesChunkNames, null, 2));
242
247
  const genRoutes = (0, utils_1.generate)(generatedFilesDir, 'routes.js', routesConfig);
243
248
  const genGlobalData = (0, utils_1.generate)(generatedFilesDir, 'globalData.json', JSON.stringify(globalData, null, 2));
@@ -293,7 +298,7 @@ ${Object.keys(registry)
293
298
  return props;
294
299
  }
295
300
  exports.load = load;
296
- // We want all @docusaurus/* packages to have the exact same version!
301
+ // We want all @docusaurus/* packages to have the exact same version!
297
302
  // See https://github.com/facebook/docusaurus/issues/3371
298
303
  // See https://github.com/facebook/docusaurus/pull/3386
299
304
  function checkDocusaurusPackagesVersion(siteMetadata) {
@@ -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 { LoadContext, PluginConfig, RouteConfig, ThemeConfig, LoadedPlugin } from '@docusaurus/types';
7
+ import type { LoadContext, PluginConfig, RouteConfig, GlobalData, ThemeConfig, LoadedPlugin } from '@docusaurus/types';
8
8
  export declare function sortConfig(routeConfigs: RouteConfig[], baseUrl?: string): void;
9
9
  export declare function loadPlugins({ pluginConfigs, context, }: {
10
10
  pluginConfigs: PluginConfig[];
@@ -12,6 +12,6 @@ export declare function loadPlugins({ pluginConfigs, context, }: {
12
12
  }): Promise<{
13
13
  plugins: LoadedPlugin[];
14
14
  pluginsRouteConfigs: RouteConfig[];
15
- globalData: unknown;
15
+ globalData: GlobalData;
16
16
  themeConfigTranslated: ThemeConfig;
17
17
  }>;
@@ -60,7 +60,7 @@ async function loadPlugins({ pluginConfigs, context, }) {
60
60
  // order-dependent. We could change this in future if there are plugins which
61
61
  // need to run in certain order or depend on others for data.
62
62
  const loadedPlugins = await Promise.all(plugins.map(async (plugin) => {
63
- const content = plugin.loadContent ? await plugin.loadContent() : null;
63
+ const content = await plugin.loadContent?.();
64
64
  return { ...plugin, content };
65
65
  }));
66
66
  const contentLoadedTranslatedPlugins = await Promise.all(loadedPlugins.map(async (contentLoadedPlugin) => {
@@ -81,7 +81,7 @@ async function loadPlugins({ pluginConfigs, context, }) {
81
81
  const allContent = lodash_1.default.chain(loadedPlugins)
82
82
  .groupBy((item) => item.name)
83
83
  .mapValues((nameItems) => lodash_1.default.chain(nameItems)
84
- .groupBy((item) => item.options.id ?? utils_1.DEFAULT_PLUGIN_ID)
84
+ .groupBy((item) => item.options.id)
85
85
  .mapValues((idItems) => idItems[0].content)
86
86
  .value())
87
87
  .value();
@@ -92,23 +92,36 @@ async function loadPlugins({ pluginConfigs, context, }) {
92
92
  if (!plugin.contentLoaded) {
93
93
  return;
94
94
  }
95
- const pluginId = plugin.options.id ?? utils_1.DEFAULT_PLUGIN_ID;
95
+ const pluginId = plugin.options.id;
96
96
  // plugins data files are namespaced by pluginName/pluginId
97
97
  const dataDirRoot = path_1.default.join(context.generatedFilesDir, plugin.name);
98
98
  const dataDir = path_1.default.join(dataDirRoot, pluginId);
99
+ const createData = async (name, data) => {
100
+ const modulePath = path_1.default.join(dataDir, name);
101
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(modulePath));
102
+ await (0, utils_1.generate)(dataDir, name, data);
103
+ return modulePath;
104
+ };
105
+ // TODO this would be better to do all that in the codegen phase
106
+ // TODO handle context for nested routes
107
+ const pluginRouteContext = {
108
+ plugin: { name: plugin.name, id: pluginId },
109
+ data: undefined, // TODO allow plugins to provide context data
110
+ };
111
+ const pluginRouteContextModulePath = await createData(`${(0, utils_1.docuHash)('pluginRouteContextModule')}.json`, JSON.stringify(pluginRouteContext, null, 2));
99
112
  const addRoute = (initialRouteConfig) => {
100
113
  // Trailing slash behavior is handled in a generic way for all plugins
101
114
  const finalRouteConfig = (0, applyRouteTrailingSlash_1.default)(initialRouteConfig, {
102
115
  trailingSlash: context.siteConfig.trailingSlash,
103
116
  baseUrl: context.siteConfig.baseUrl,
104
117
  });
105
- pluginsRouteConfigs.push(finalRouteConfig);
106
- };
107
- const createData = async (name, data) => {
108
- const modulePath = path_1.default.join(dataDir, name);
109
- await fs_extra_1.default.ensureDir(path_1.default.dirname(modulePath));
110
- await (0, utils_1.generate)(dataDir, name, data);
111
- return modulePath;
118
+ pluginsRouteConfigs.push({
119
+ ...finalRouteConfig,
120
+ modules: {
121
+ ...finalRouteConfig.modules,
122
+ __routeContextModule: pluginRouteContextModulePath,
123
+ },
124
+ });
112
125
  };
113
126
  // the plugins global data are namespaced to avoid data conflicts:
114
127
  // - by plugin name
@@ -135,13 +148,13 @@ async function loadPlugins({ pluginConfigs, context, }) {
135
148
  // need to run in certain order or depend on others for data.
136
149
  await Promise.all(contentLoadedTranslatedPlugins.map(async (plugin) => {
137
150
  if (!plugin.routesLoaded) {
138
- return null;
151
+ return;
139
152
  }
140
153
  // TODO remove this deprecated lifecycle soon
141
154
  // deprecated since alpha-60
142
155
  // TODO, 1 user reported usage of this lifecycle! https://github.com/facebook/docusaurus/issues/3918
143
156
  logger_1.default.error `Plugin code=${'routesLoaded'} lifecycle is deprecated. If you think we should keep this lifecycle, please report here: path=${'https://github.com/facebook/docusaurus/issues/3918'}`;
144
- return plugin.routesLoaded(pluginsRouteConfigs);
157
+ await plugin.routesLoaded(pluginsRouteConfigs);
145
158
  }));
146
159
  // Sort the route config. This ensures that route with nested
147
160
  // routes are always placed last.
@@ -4,7 +4,6 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- /// <reference types="node" />
8
7
  import type { ImportedPluginModule, LoadContext, PluginModule, PluginConfig, PluginOptions, InitializedPlugin } from '@docusaurus/types';
9
8
  export declare type NormalizedPluginConfig = {
10
9
  plugin: PluginModule;
@@ -13,8 +12,13 @@ export declare type NormalizedPluginConfig = {
13
12
  path: string;
14
13
  module: ImportedPluginModule;
15
14
  };
15
+ /**
16
+ * Different from pluginModule.path, this one is always an absolute path used
17
+ * to resolve relative paths returned from lifecycles
18
+ */
19
+ entryPath: string;
16
20
  };
17
- export declare function normalizePluginConfigs(pluginConfigs: PluginConfig[], pluginRequire: NodeRequire): Promise<NormalizedPluginConfig[]>;
21
+ export declare function normalizePluginConfigs(pluginConfigs: PluginConfig[], configPath: string): Promise<NormalizedPluginConfig[]>;
18
22
  export default function initPlugins({ pluginConfigs, context, }: {
19
23
  pluginConfigs: PluginConfig[];
20
24
  context: LoadContext;
@@ -9,12 +9,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.normalizePluginConfigs = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const module_1 = require("module");
12
+ const path_1 = tslib_1.__importDefault(require("path"));
12
13
  const import_fresh_1 = tslib_1.__importDefault(require("import-fresh"));
13
14
  const utils_1 = require("@docusaurus/utils");
14
15
  const versions_1 = require("../versions");
15
16
  const pluginIds_1 = require("./pluginIds");
16
17
  const utils_validation_1 = require("@docusaurus/utils-validation");
17
- async function normalizePluginConfig(pluginConfig, pluginRequire) {
18
+ async function normalizePluginConfig(pluginConfig, configPath) {
19
+ const pluginRequire = (0, module_1.createRequire)(configPath);
18
20
  // plugins: ['./plugin']
19
21
  if (typeof pluginConfig === 'string') {
20
22
  const pluginModuleImport = pluginConfig;
@@ -27,6 +29,7 @@ async function normalizePluginConfig(pluginConfig, pluginRequire) {
27
29
  path: pluginModuleImport,
28
30
  module: pluginModule,
29
31
  },
32
+ entryPath: pluginPath,
30
33
  };
31
34
  }
32
35
  // plugins: [function plugin() { }]
@@ -34,39 +37,37 @@ async function normalizePluginConfig(pluginConfig, pluginRequire) {
34
37
  return {
35
38
  plugin: pluginConfig,
36
39
  options: {},
40
+ entryPath: configPath,
37
41
  };
38
42
  }
39
- if (Array.isArray(pluginConfig)) {
40
- // plugins: [
41
- // ['./plugin',options],
42
- // ]
43
- if (typeof pluginConfig[0] === 'string') {
44
- const pluginModuleImport = pluginConfig[0];
45
- const pluginPath = pluginRequire.resolve(pluginModuleImport);
46
- const pluginModule = (0, import_fresh_1.default)(pluginPath);
47
- return {
48
- plugin: pluginModule?.default ?? pluginModule,
49
- options: pluginConfig[1] ?? {},
50
- pluginModule: {
51
- path: pluginModuleImport,
52
- module: pluginModule,
53
- },
54
- };
55
- }
56
- // plugins: [
57
- // [function plugin() { },options],
58
- // ]
59
- if (typeof pluginConfig[0] === 'function') {
60
- return {
61
- plugin: pluginConfig[0],
62
- options: pluginConfig[1] ?? {},
63
- };
64
- }
43
+ // plugins: [
44
+ // ['./plugin',options],
45
+ // ]
46
+ if (typeof pluginConfig[0] === 'string') {
47
+ const pluginModuleImport = pluginConfig[0];
48
+ const pluginPath = pluginRequire.resolve(pluginModuleImport);
49
+ const pluginModule = (0, import_fresh_1.default)(pluginPath);
50
+ return {
51
+ plugin: pluginModule?.default ?? pluginModule,
52
+ options: pluginConfig[1],
53
+ pluginModule: {
54
+ path: pluginModuleImport,
55
+ module: pluginModule,
56
+ },
57
+ entryPath: pluginPath,
58
+ };
65
59
  }
66
- throw new Error(`Unexpected: can't load plugin for following plugin config.\n${JSON.stringify(pluginConfig)}`);
60
+ // plugins: [
61
+ // [function plugin() { },options],
62
+ // ]
63
+ return {
64
+ plugin: pluginConfig[0],
65
+ options: pluginConfig[1],
66
+ entryPath: configPath,
67
+ };
67
68
  }
68
- async function normalizePluginConfigs(pluginConfigs, pluginRequire) {
69
- return Promise.all(pluginConfigs.map((pluginConfig) => normalizePluginConfig(pluginConfig, pluginRequire)));
69
+ async function normalizePluginConfigs(pluginConfigs, configPath) {
70
+ return Promise.all(pluginConfigs.map((pluginConfig) => normalizePluginConfig(pluginConfig, configPath)));
70
71
  }
71
72
  exports.normalizePluginConfigs = normalizePluginConfigs;
72
73
  function getOptionValidationFunction(normalizedPluginConfig) {
@@ -89,7 +90,7 @@ async function initPlugins({ pluginConfigs, context, }) {
89
90
  // We need to resolve plugins from the perspective of the siteDir, since the
90
91
  // siteDir's package.json declares the dependency on these plugins.
91
92
  const pluginRequire = (0, module_1.createRequire)(context.siteConfigPath);
92
- const pluginConfigsNormalized = await normalizePluginConfigs(pluginConfigs, pluginRequire);
93
+ const pluginConfigsNormalized = await normalizePluginConfigs(pluginConfigs, context.siteConfigPath);
93
94
  async function doGetPluginVersion(normalizedPluginConfig) {
94
95
  // get plugin version
95
96
  if (normalizedPluginConfig.pluginModule?.path) {
@@ -136,14 +137,10 @@ async function initPlugins({ pluginConfigs, context, }) {
136
137
  ...pluginInstance,
137
138
  options: pluginOptions,
138
139
  version: pluginVersion,
140
+ path: path_1.default.dirname(normalizedPluginConfig.entryPath),
139
141
  };
140
142
  }
141
- const plugins = (await Promise.all(pluginConfigsNormalized.map((pluginConfig) => {
142
- if (!pluginConfig) {
143
- return null;
144
- }
145
- return initializePlugin(pluginConfig);
146
- }))).filter((item) => Boolean(item));
143
+ const plugins = await Promise.all(pluginConfigsNormalized.map(initializePlugin));
147
144
  (0, pluginIds_1.ensureUniquePluginInstanceIds)(plugins);
148
145
  return plugins;
149
146
  }