@docusaurus/core 3.9.2 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1 +1,3 @@
1
- # Docusaurus core
1
+ # `@docusaurus/core`
2
+
3
+ The core package of Docusaurus
@@ -4,11 +4,4 @@
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
- declare global {
8
- interface NodeModule {
9
- hot?: {
10
- accept: () => void;
11
- };
12
- }
13
- }
14
7
  export {};
@@ -5,9 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  declare global {
8
- const __webpack_require__: {
9
- gca: (name: string) => string;
10
- };
11
8
  interface Navigator {
12
9
  connection?: {
13
10
  effectiveType: string;
@@ -5,9 +5,4 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import Loadable from 'react-loadable';
8
- declare global {
9
- interface NodeRequire {
10
- resolveWeak: (name: string) => number;
11
- }
12
- }
13
8
  export default function ComponentCreator(path: string, hash: string): ReturnType<typeof Loadable>;
@@ -63,7 +63,7 @@ function Link({ isNavLink, to, href, activeClassName, isActive, 'data-noBrokenLi
63
63
  const preloaded = useRef(false);
64
64
  const LinkComponent = (isNavLink ? NavLink : RRLink);
65
65
  const IOSupported = ExecutionEnvironment.canUseIntersectionObserver;
66
- const ioRef = useRef();
66
+ const ioRef = useRef(undefined);
67
67
  const handleRef = (el) => {
68
68
  innerRef.current = el;
69
69
  if (IOSupported && el && isInternal) {
@@ -4,8 +4,11 @@
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
+ // Poor man's protocol detection
8
+ // Spec: https://datatracker.ietf.org/doc/html/rfc3986#section-3.1
9
+ // In particular: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
7
10
  export function hasProtocol(url) {
8
- return /^(?:\w*:|\/\/)/.test(url);
11
+ return /^(?:[A-Za-z][A-Za-z\d+.-]*:|\/\/)/.test(url);
9
12
  }
10
13
  export default function isInternalUrl(url) {
11
14
  return typeof url !== 'undefined' && !hasProtocol(url);
@@ -11,10 +11,9 @@ const tslib_1 = require("tslib");
11
11
  const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
12
12
  const logger_1 = tslib_1.__importStar(require("@docusaurus/logger"));
13
13
  const utils_1 = require("@docusaurus/utils");
14
- const site_1 = require("../../server/site");
15
14
  const i18n_1 = require("../../server/i18n");
16
15
  const buildLocale_1 = require("./buildLocale");
17
- const buildUtils_1 = require("./buildUtils");
16
+ const config_1 = require("../../server/config");
18
17
  async function build(siteDirParam = '.', cliOptions = {}) {
19
18
  process.env.BABEL_ENV = 'production';
20
19
  process.env.NODE_ENV = 'production';
@@ -50,24 +49,18 @@ function orderLocales({ locales, defaultLocale, }) {
50
49
  }
51
50
  }
52
51
  async function getLocalesToBuild({ siteDir, cliOptions, }) {
53
- // TODO we shouldn't need to load all context + i18n just to get that list
54
- // only loading siteConfig should be enough
55
- const context = await (0, site_1.loadContext)({
52
+ const { siteConfig } = await (0, config_1.loadSiteConfig)({
56
53
  siteDir,
57
- outDir: cliOptions.outDir,
58
- config: cliOptions.config,
59
- automaticBaseUrlLocalizationDisabled: (0, buildUtils_1.isAutomaticBaseUrlLocalizationDisabled)(cliOptions),
54
+ customConfigFilePath: cliOptions.config,
60
55
  });
61
- const i18n = await (0, i18n_1.loadI18n)({
62
- siteDir,
63
- config: context.siteConfig,
64
- currentLocale: context.siteConfig.i18n.defaultLocale, // Awkward but ok
65
- automaticBaseUrlLocalizationDisabled: false,
66
- });
67
- const locales = cliOptions.locale ?? i18n.locales;
56
+ const locales = cliOptions.locale ??
57
+ (0, i18n_1.getLocaleList)({
58
+ i18nConfig: siteConfig.i18n,
59
+ currentLocale: siteConfig.i18n.defaultLocale, // Awkward but ok
60
+ });
68
61
  return orderLocales({
69
62
  locales: locales,
70
- defaultLocale: i18n.defaultLocale,
63
+ defaultLocale: siteConfig.i18n.defaultLocale,
71
64
  });
72
65
  }
73
66
  async function tryToBuildLocale(params) {
@@ -22,6 +22,7 @@ const ssgExecutor_1 = require("../../ssg/ssgExecutor");
22
22
  const clearPath_1 = tslib_1.__importDefault(require("../utils/clearPath"));
23
23
  const buildUtils_1 = require("./buildUtils");
24
24
  const SkipBundling = process.env.DOCUSAURUS_SKIP_BUNDLING === 'true';
25
+ const ReturnAfterLoading = process.env.DOCUSAURUS_RETURN_AFTER_LOADING === 'true';
25
26
  const ExitAfterLoading = process.env.DOCUSAURUS_EXIT_AFTER_LOADING === 'true';
26
27
  const ExitAfterBundling = process.env.DOCUSAURUS_EXIT_AFTER_BUNDLING === 'true';
27
28
  async function buildLocale({ siteDir, locale, cliOptions, }) {
@@ -37,6 +38,9 @@ async function buildLocale({ siteDir, locale, cliOptions, }) {
37
38
  locale,
38
39
  automaticBaseUrlLocalizationDisabled: (0, buildUtils_1.isAutomaticBaseUrlLocalizationDisabled)(cliOptions),
39
40
  }));
41
+ if (ReturnAfterLoading) {
42
+ return;
43
+ }
40
44
  if (ExitAfterLoading) {
41
45
  return process.exit(0);
42
46
  }
@@ -128,7 +132,7 @@ async function getBuildClientConfig({ props, cliOptions, configureWebpackUtils,
128
132
  const result = await (0, client_1.createBuildClientConfig)({
129
133
  props,
130
134
  minify: cliOptions.minify ?? true,
131
- faster: props.siteConfig.future.experimental_faster,
135
+ faster: props.siteConfig.future.faster,
132
136
  configureWebpackUtils,
133
137
  bundleAnalyzer: cliOptions.bundleAnalyzer ?? false,
134
138
  });
@@ -135,8 +135,10 @@ async function createCLIProgram({ cli, cliArgs, siteDir, config, }) {
135
135
  cli
136
136
  .command('write-heading-ids [siteDir] [files...]')
137
137
  .description('Generate heading ids in Markdown content.')
138
+ .option('--syntax <syntax>', 'heading ID syntax: "classic" ({#id}) or "mdx-comment" ({/* #id */}) (default: "classic")')
139
+ .option('--migrate', 'migrate existing heading IDs to the target --syntax, if they are using a different syntax (default: false)')
140
+ .option('--overwrite', 'overwrite existing heading IDs, re-generate them from the heading text (default: false)')
138
141
  .option('--maintain-case', "keep the headings' casing, otherwise make all lowercase (default: false)")
139
- .option('--overwrite', 'overwrite existing heading IDs (default: false)')
140
142
  .action(writeHeadingIds_1.writeHeadingIds);
141
143
  cli.arguments('<command>').action((cmd) => {
142
144
  cli.outputHelp();
@@ -102,7 +102,7 @@ async function getStartClientConfig({ props, minify, poll, configureWebpackUtils
102
102
  let { clientConfig: config } = await (0, client_1.createStartClientConfig)({
103
103
  props,
104
104
  minify,
105
- faster: props.siteConfig.future.experimental_faster,
105
+ faster: props.siteConfig.future.faster,
106
106
  poll,
107
107
  configureWebpackUtils,
108
108
  });
@@ -10,7 +10,6 @@ exports.swizzle = swizzle;
10
10
  const tslib_1 = require("tslib");
11
11
  const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
12
12
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
13
- const utils_1 = require("@docusaurus/utils");
14
13
  const themes_1 = require("./themes");
15
14
  const components_1 = require("./components");
16
15
  const tables_1 = require("./tables");
@@ -33,7 +32,7 @@ async function getLanguageForThemeName({ themeName, plugins, options, }) {
33
32
  }
34
33
  // It's only useful to prompt the user for themes that support both JS/TS
35
34
  if (supportsTS) {
36
- return (0, utils_1.askPreferredLanguage)({ exit: true });
35
+ return (0, prompts_1.askSwizzlePreferredLanguage)();
37
36
  }
38
37
  return 'javascript';
39
38
  }
@@ -10,3 +10,4 @@ export declare function askThemeName(themeNames: string[]): Promise<string>;
10
10
  export declare function askComponentName(themeComponents: ThemeComponents): Promise<string>;
11
11
  export declare function askSwizzleDangerousComponent(): Promise<boolean>;
12
12
  export declare function askSwizzleAction(componentConfig: SwizzleComponentConfig): Promise<SwizzleAction>;
13
+ export declare function askSwizzlePreferredLanguage(): Promise<'javascript' | 'typescript'>;
@@ -10,6 +10,7 @@ exports.askThemeName = askThemeName;
10
10
  exports.askComponentName = askComponentName;
11
11
  exports.askSwizzleDangerousComponent = askSwizzleDangerousComponent;
12
12
  exports.askSwizzleAction = askSwizzleAction;
13
+ exports.askSwizzlePreferredLanguage = askSwizzlePreferredLanguage;
13
14
  const tslib_1 = require("tslib");
14
15
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
15
16
  const prompts_1 = tslib_1.__importDefault(require("prompts"));
@@ -107,3 +108,24 @@ async function askSwizzleAction(componentConfig) {
107
108
  }
108
109
  return action;
109
110
  }
111
+ async function askSwizzlePreferredLanguage() {
112
+ const choices = [
113
+ { title: logger_1.default.bold('JavaScript'), value: 'javascript' },
114
+ { title: logger_1.default.bold('TypeScript'), value: 'typescript' },
115
+ { title: logger_1.default.yellow('[Exit]'), value: '[Exit]' },
116
+ ];
117
+ const { language } = await (0, prompts_1.default)({
118
+ type: 'select',
119
+ name: 'language',
120
+ message: 'Which language do you want to use?',
121
+ choices,
122
+ }, {
123
+ onCancel() {
124
+ process.exit(0);
125
+ },
126
+ });
127
+ if (typeof language === 'undefined' || language === '[Exit]') {
128
+ process.exit(0);
129
+ }
130
+ return language;
131
+ }
@@ -69,6 +69,9 @@ async function tryOpenWithAppleScript({ url, browser, }) {
69
69
  // We open Google Chrome Canary in priority over Google Chrome
70
70
  return supportedChromiumBrowsers.filter((b) => activeBrowsers.includes(b));
71
71
  }
72
+ // Test this manually with:
73
+ // osascript ./packages/docusaurus/src/commands/utils/openBrowser/openChrome.applescript "http://localhost:8080" "Google Chrome"
74
+ // osascript ./packages/docusaurus/src/commands/utils/openBrowser/openChrome.applescript "http://localhost:8080" "Arc"
72
75
  async function tryBrowser(browserName) {
73
76
  try {
74
77
  // This command runs the openChrome.applescript (copied from CRA)
@@ -19,6 +19,16 @@ on run argv
19
19
  set theProgram to item 2 of argv
20
20
  end if
21
21
 
22
+ -- Arc: simple open + activate, no tab reuse
23
+ -- See https://github.com/facebook/docusaurus/issues/11582
24
+ if theProgram is "Arc" then
25
+ tell application "Arc"
26
+ activate
27
+ open location theURL
28
+ end tell
29
+ return
30
+ end if
31
+
22
32
  using terms from application "Google Chrome"
23
33
  tell application theProgram
24
34
 
@@ -13,9 +13,25 @@ const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
13
13
  const utils_1 = require("@docusaurus/utils");
14
14
  const site_1 = require("../server/site");
15
15
  const init_1 = require("../server/plugins/init");
16
+ function inferFallbackSyntax(_filepath) {
17
+ // TODO Docusaurus v4 - infer the syntax based on the file extensions?
18
+ // This is not ideal because we have many ways to define the syntax
19
+ // (front matter "format", siteConfig.markdown.format etc...)
20
+ // but probably good enough for now
21
+ // Until then, we default to the classic syntax
22
+ // The mdx-comment syntax is opt-in
23
+ return 'classic';
24
+ }
25
+ function getHeadingIdSyntax(filepath, options) {
26
+ return options?.syntax ?? inferFallbackSyntax(filepath);
27
+ }
16
28
  async function transformMarkdownFile(filepath, options) {
17
29
  const content = await fs_extra_1.default.readFile(filepath, 'utf8');
18
- const updatedContent = (0, utils_1.writeMarkdownHeadingId)(content, options);
30
+ const syntax = getHeadingIdSyntax(filepath, options);
31
+ const updatedContent = (0, utils_1.writeMarkdownHeadingId)(content, {
32
+ ...options,
33
+ syntax,
34
+ });
19
35
  if (content !== updatedContent) {
20
36
  await fs_extra_1.default.writeFile(filepath, updatedContent);
21
37
  return filepath;
@@ -33,17 +49,35 @@ async function getPathsToWatch(siteDir) {
33
49
  const plugins = await (0, init_1.initPlugins)(context);
34
50
  return plugins.flatMap((plugin) => plugin.getPathsToWatch?.() ?? []);
35
51
  }
52
+ // TODO Docusaurus v4 - Upgrade commander, use choices() API?
53
+ function validateOptions(options) {
54
+ const validSyntaxValues = ['classic', 'mdx-comment'];
55
+ if (options.syntax && !validSyntaxValues.includes(options.syntax)) {
56
+ throw new Error(`Invalid --syntax value "${options.syntax}". Valid values: ${validSyntaxValues.join(', ')}`);
57
+ }
58
+ if (options.overwrite && options.migrate) {
59
+ throw new Error("Options --overwrite and --migrate cannot be used together.\nThe --overwrite already re-generates IDs in the target syntax, so the --migrate option wouldn't have any effect.");
60
+ }
61
+ }
36
62
  async function writeHeadingIds(siteDirParam = '.', files = [], options = {}) {
63
+ validateOptions(options);
37
64
  const siteDir = await fs_extra_1.default.realpath(siteDirParam);
38
- const markdownFiles = await (0, utils_1.safeGlobby)(files ?? (await getPathsToWatch(siteDir)), {
65
+ const patterns = files.length ? files : await getPathsToWatch(siteDir);
66
+ const markdownFiles = await (0, utils_1.safeGlobby)(patterns, {
39
67
  expandDirectories: ['**/*.{md,mdx}'],
40
68
  });
69
+ if (markdownFiles.length === 0) {
70
+ logger_1.default.warn `No markdown files found in siteDir path=${siteDir} for patterns: ${patterns}`;
71
+ return;
72
+ }
41
73
  const result = await Promise.all(markdownFiles.map((p) => transformMarkdownFile(p, options)));
42
74
  const pathsModified = result.filter(Boolean);
43
75
  if (pathsModified.length) {
44
76
  logger_1.default.success `Heading ids added to Markdown files (number=${`${pathsModified.length}/${markdownFiles.length}`} files): ${pathsModified}`;
45
77
  }
46
78
  else {
47
- logger_1.default.warn `number=${markdownFiles.length} Markdown files already have explicit heading IDs. If you intend to overwrite the existing heading IDs, use the code=${'--overwrite'} option.`;
79
+ logger_1.default.warn `number=${markdownFiles.length} Markdown files already have explicit heading IDs.
80
+ If you intend to overwrite the existing heading IDs, use the code=${'--overwrite'} option.
81
+ If you intend to change their heading ID syntax, use the code=${'--migrate'} option.`;
48
82
  }
49
83
  }
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { Joi } from '@docusaurus/utils-validation';
8
- import type { FasterConfig, FutureConfig, FutureV4Config, StorageConfig, DocusaurusConfig, I18nConfig, MarkdownConfig, MarkdownHooks } from '@docusaurus/types';
8
+ import type { DocusaurusConfig, FasterConfig, FutureConfig, FutureV4Config, I18nConfig, MDX1CompatOptions, MarkdownConfig, MarkdownHooks, StorageConfig } from '@docusaurus/types';
9
9
  export declare const DEFAULT_I18N_CONFIG: I18nConfig;
10
10
  export declare const DEFAULT_STORAGE_CONFIG: StorageConfig;
11
11
  export declare const DEFAULT_FASTER_CONFIG: FasterConfig;
@@ -14,7 +14,8 @@ export declare const DEFAULT_FUTURE_V4_CONFIG: FutureV4Config;
14
14
  export declare const DEFAULT_FUTURE_V4_CONFIG_TRUE: FutureV4Config;
15
15
  export declare const DEFAULT_FUTURE_CONFIG: FutureConfig;
16
16
  export declare const DEFAULT_MARKDOWN_HOOKS: MarkdownHooks;
17
+ export declare const DEFAULT_MARKDOWN_MDX1COMPAT: MDX1CompatOptions;
17
18
  export declare const DEFAULT_MARKDOWN_CONFIG: MarkdownConfig;
18
- export declare const DEFAULT_CONFIG: Pick<DocusaurusConfig, 'i18n' | 'future' | 'onBrokenLinks' | 'onBrokenAnchors' | 'onBrokenMarkdownLinks' | 'onDuplicateRoutes' | 'plugins' | 'themes' | 'presets' | 'headTags' | 'stylesheets' | 'scripts' | 'clientModules' | 'customFields' | 'themeConfig' | 'titleDelimiter' | 'noIndex' | 'tagline' | 'baseUrlIssueBanner' | 'staticDirectories' | 'markdown'>;
19
+ export declare const DEFAULT_CONFIG: Pick<DocusaurusConfig, 'i18n' | 'storage' | 'future' | 'onBrokenLinks' | 'onBrokenAnchors' | 'onBrokenMarkdownLinks' | 'onDuplicateRoutes' | 'plugins' | 'themes' | 'presets' | 'headTags' | 'stylesheets' | 'scripts' | 'clientModules' | 'customFields' | 'themeConfig' | 'titleDelimiter' | 'noIndex' | 'tagline' | 'baseUrlIssueBanner' | 'staticDirectories' | 'markdown'>;
19
20
  export declare const ConfigSchema: Joi.ObjectSchema<DocusaurusConfig>;
20
21
  export declare function validateConfig(config: unknown, siteConfigPath: string): DocusaurusConfig;
@@ -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.ConfigSchema = exports.DEFAULT_CONFIG = exports.DEFAULT_MARKDOWN_CONFIG = exports.DEFAULT_MARKDOWN_HOOKS = exports.DEFAULT_FUTURE_CONFIG = exports.DEFAULT_FUTURE_V4_CONFIG_TRUE = exports.DEFAULT_FUTURE_V4_CONFIG = exports.DEFAULT_FASTER_CONFIG_TRUE = exports.DEFAULT_FASTER_CONFIG = exports.DEFAULT_STORAGE_CONFIG = exports.DEFAULT_I18N_CONFIG = void 0;
9
+ exports.ConfigSchema = exports.DEFAULT_CONFIG = exports.DEFAULT_MARKDOWN_CONFIG = exports.DEFAULT_MARKDOWN_MDX1COMPAT = exports.DEFAULT_MARKDOWN_HOOKS = exports.DEFAULT_FUTURE_CONFIG = exports.DEFAULT_FUTURE_V4_CONFIG_TRUE = exports.DEFAULT_FUTURE_V4_CONFIG = exports.DEFAULT_FASTER_CONFIG_TRUE = exports.DEFAULT_FASTER_CONFIG = exports.DEFAULT_STORAGE_CONFIG = exports.DEFAULT_I18N_CONFIG = void 0;
10
10
  exports.validateConfig = validateConfig;
11
11
  const tslib_1 = require("tslib");
12
12
  const utils_1 = require("@docusaurus/utils");
@@ -55,6 +55,7 @@ exports.DEFAULT_FASTER_CONFIG = {
55
55
  rspackBundler: false,
56
56
  rspackPersistentCache: false,
57
57
  ssgWorkerThreads: false,
58
+ gitEagerVcs: false,
58
59
  };
59
60
  // When using the "faster: true" shortcut
60
61
  exports.DEFAULT_FASTER_CONFIG_TRUE = {
@@ -66,37 +67,48 @@ exports.DEFAULT_FASTER_CONFIG_TRUE = {
66
67
  rspackBundler: true,
67
68
  rspackPersistentCache: true,
68
69
  ssgWorkerThreads: true,
70
+ gitEagerVcs: true,
69
71
  };
70
72
  exports.DEFAULT_FUTURE_V4_CONFIG = {
71
73
  removeLegacyPostBuildHeadAttribute: false,
72
74
  useCssCascadeLayers: false,
75
+ siteStorageNamespacing: false,
76
+ fasterByDefault: false,
77
+ mdx1CompatDisabledByDefault: false,
73
78
  };
74
79
  // When using the "v4: true" shortcut
75
80
  exports.DEFAULT_FUTURE_V4_CONFIG_TRUE = {
76
81
  removeLegacyPostBuildHeadAttribute: true,
77
82
  useCssCascadeLayers: true,
83
+ siteStorageNamespacing: true,
84
+ fasterByDefault: true,
85
+ mdx1CompatDisabledByDefault: true,
78
86
  };
79
87
  exports.DEFAULT_FUTURE_CONFIG = {
80
88
  v4: exports.DEFAULT_FUTURE_V4_CONFIG,
81
- experimental_faster: exports.DEFAULT_FASTER_CONFIG,
82
- experimental_storage: exports.DEFAULT_STORAGE_CONFIG,
89
+ faster: exports.DEFAULT_FASTER_CONFIG,
90
+ experimental_vcs: (0, utils_1.getVcsPreset)('default-v1'),
83
91
  experimental_router: 'browser',
84
92
  };
85
93
  exports.DEFAULT_MARKDOWN_HOOKS = {
86
94
  onBrokenMarkdownLinks: 'warn',
87
95
  onBrokenMarkdownImages: 'throw',
88
96
  };
97
+ exports.DEFAULT_MARKDOWN_MDX1COMPAT = {
98
+ comments: true,
99
+ admonitions: true,
100
+ headingIds: true,
101
+ };
89
102
  exports.DEFAULT_MARKDOWN_CONFIG = {
90
- format: 'mdx', // TODO change this to "detect" in Docusaurus v4?
103
+ // TODO Docusaurus v5: change this to "detect"?
104
+ // we probably need stable CommonMark support first
105
+ // see https://github.com/facebook/docusaurus/issues/9092
106
+ format: 'mdx',
91
107
  mermaid: false,
92
108
  emoji: true,
93
109
  preprocessor: undefined,
94
110
  parseFrontMatter: utils_1.DEFAULT_PARSE_FRONT_MATTER,
95
- mdx1Compat: {
96
- comments: true,
97
- admonitions: true,
98
- headingIds: true,
99
- },
111
+ mdx1Compat: exports.DEFAULT_MARKDOWN_MDX1COMPAT,
100
112
  anchors: {
101
113
  maintainCase: false,
102
114
  },
@@ -105,6 +117,7 @@ exports.DEFAULT_MARKDOWN_CONFIG = {
105
117
  };
106
118
  exports.DEFAULT_CONFIG = {
107
119
  i18n: exports.DEFAULT_I18N_CONFIG,
120
+ storage: exports.DEFAULT_STORAGE_CONFIG,
108
121
  future: exports.DEFAULT_FUTURE_CONFIG,
109
122
  onBrokenLinks: 'throw',
110
123
  onBrokenAnchors: 'warn', // TODO Docusaurus v4: change to throw
@@ -194,25 +207,31 @@ const I18N_CONFIG_SCHEMA = utils_validation_1.Joi.object({
194
207
  })
195
208
  .optional()
196
209
  .default(exports.DEFAULT_I18N_CONFIG);
210
+ // Individual boolean defaults are not set here on purpose
211
+ // They are resolved in postProcessDocusaurusConfig based on
212
+ // the future.v4.fasterByDefault flag
197
213
  const FASTER_CONFIG_SCHEMA = utils_validation_1.Joi.alternatives()
198
214
  .try(utils_validation_1.Joi.object({
199
- swcJsLoader: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FASTER_CONFIG.swcJsLoader),
200
- swcJsMinimizer: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FASTER_CONFIG.swcJsMinimizer),
201
- swcHtmlMinimizer: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FASTER_CONFIG.swcHtmlMinimizer),
202
- lightningCssMinimizer: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FASTER_CONFIG.lightningCssMinimizer),
203
- mdxCrossCompilerCache: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FASTER_CONFIG.mdxCrossCompilerCache),
204
- rspackBundler: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FASTER_CONFIG.rspackBundler),
205
- rspackPersistentCache: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FASTER_CONFIG.rspackPersistentCache),
206
- ssgWorkerThreads: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FASTER_CONFIG.ssgWorkerThreads),
215
+ swcJsLoader: utils_validation_1.Joi.boolean(),
216
+ swcJsMinimizer: utils_validation_1.Joi.boolean(),
217
+ swcHtmlMinimizer: utils_validation_1.Joi.boolean(),
218
+ lightningCssMinimizer: utils_validation_1.Joi.boolean(),
219
+ mdxCrossCompilerCache: utils_validation_1.Joi.boolean(),
220
+ rspackBundler: utils_validation_1.Joi.boolean(),
221
+ rspackPersistentCache: utils_validation_1.Joi.boolean(),
222
+ ssgWorkerThreads: utils_validation_1.Joi.boolean(),
223
+ gitEagerVcs: utils_validation_1.Joi.boolean(),
207
224
  }), utils_validation_1.Joi.boolean()
208
225
  .required()
209
226
  .custom((bool) => bool ? exports.DEFAULT_FASTER_CONFIG_TRUE : exports.DEFAULT_FASTER_CONFIG))
210
- .optional()
211
- .default(exports.DEFAULT_FASTER_CONFIG);
227
+ .optional();
212
228
  const FUTURE_V4_SCHEMA = utils_validation_1.Joi.alternatives()
213
229
  .try(utils_validation_1.Joi.object({
214
230
  removeLegacyPostBuildHeadAttribute: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.removeLegacyPostBuildHeadAttribute),
215
231
  useCssCascadeLayers: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.useCssCascadeLayers),
232
+ siteStorageNamespacing: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.siteStorageNamespacing),
233
+ fasterByDefault: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.fasterByDefault),
234
+ mdx1CompatDisabledByDefault: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.mdx1CompatDisabledByDefault),
216
235
  }), utils_validation_1.Joi.boolean()
217
236
  .required()
218
237
  .custom((bool) => bool ? exports.DEFAULT_FUTURE_V4_CONFIG_TRUE : exports.DEFAULT_FUTURE_V4_CONFIG))
@@ -222,19 +241,58 @@ const STORAGE_CONFIG_SCHEMA = utils_validation_1.Joi.object({
222
241
  type: utils_validation_1.Joi.string()
223
242
  .equal('localStorage', 'sessionStorage')
224
243
  .default(exports.DEFAULT_STORAGE_CONFIG.type),
225
- namespace: utils_validation_1.Joi.alternatives()
226
- .try(utils_validation_1.Joi.string(), utils_validation_1.Joi.boolean())
227
- .default(exports.DEFAULT_STORAGE_CONFIG.namespace),
244
+ // namespace default is not set here on purpose
245
+ // It is resolved in postProcessDocusaurusConfig based on
246
+ // the future.v4.siteStorageNamespacing flag
247
+ namespace: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.string(), utils_validation_1.Joi.boolean()),
228
248
  })
229
249
  .optional()
230
- .default(exports.DEFAULT_STORAGE_CONFIG);
250
+ .default({ type: exports.DEFAULT_STORAGE_CONFIG.type });
251
+ const VCS_CONFIG_OBJECT_SCHEMA = utils_validation_1.Joi.object({
252
+ // All the fields are required on purpose
253
+ // You either provide a full VCS config or nothing
254
+ initialize: utils_validation_1.Joi.function().maxArity(1).required(),
255
+ getFileCreationInfo: utils_validation_1.Joi.function().arity(1).required(),
256
+ getFileLastUpdateInfo: utils_validation_1.Joi.function().arity(1).required(),
257
+ });
258
+ const VCS_CONFIG_SCHEMA = utils_validation_1.Joi.custom((input) => {
259
+ if (typeof input === 'string') {
260
+ const presetName = input;
261
+ if (!utils_1.VcsPresetNames.includes(presetName)) {
262
+ throw new Error(`VCS config preset name '${input}' is not valid.`);
263
+ }
264
+ return (0, utils_1.getVcsPreset)(presetName);
265
+ }
266
+ if (typeof input === 'boolean') {
267
+ // We return the boolean on purpose
268
+ // We'll normalize it to a real VcsConfig later
269
+ // This is annoying, but we have to read the future flag to switch to the
270
+ // new "default-v2" config (not easy to do it here)
271
+ return input;
272
+ }
273
+ const { error, value } = VCS_CONFIG_OBJECT_SCHEMA.validate(input);
274
+ if (error) {
275
+ throw error;
276
+ }
277
+ return value;
278
+ }).default(true);
231
279
  const FUTURE_CONFIG_SCHEMA = utils_validation_1.Joi.object({
232
280
  v4: FUTURE_V4_SCHEMA,
233
- experimental_faster: FASTER_CONFIG_SCHEMA,
234
- experimental_storage: STORAGE_CONFIG_SCHEMA,
281
+ faster: FASTER_CONFIG_SCHEMA,
282
+ experimental_vcs: VCS_CONFIG_SCHEMA,
235
283
  experimental_router: utils_validation_1.Joi.string()
236
284
  .equal('browser', 'hash')
237
285
  .default(exports.DEFAULT_FUTURE_CONFIG.experimental_router),
286
+ experimental_storage: utils_validation_1.Joi.any()
287
+ .forbidden()
288
+ .messages({
289
+ 'any.unknown': `The Docusaurus config ${logger_1.default.code('future.experimental_storage')} has been promoted to a stable top-level ${logger_1.default.code('storage')} config attribute. Please move your storage config to the top level.`,
290
+ }),
291
+ experimental_faster: utils_validation_1.Joi.any()
292
+ .forbidden()
293
+ .messages({
294
+ 'any.unknown': `The Docusaurus config ${logger_1.default.code('future.experimental_faster')} has been renamed to ${logger_1.default.code('future.faster')}. Please update your Docusaurus config.`,
295
+ }),
238
296
  })
239
297
  .optional()
240
298
  .default(exports.DEFAULT_FUTURE_CONFIG);
@@ -247,6 +305,7 @@ exports.ConfigSchema = utils_validation_1.Joi.object({
247
305
  title: utils_validation_1.Joi.string().required(),
248
306
  trailingSlash: utils_validation_1.Joi.boolean(), // No default value! undefined = retrocompatible legacy behavior!
249
307
  i18n: I18N_CONFIG_SCHEMA,
308
+ storage: STORAGE_CONFIG_SCHEMA,
250
309
  future: FUTURE_CONFIG_SCHEMA,
251
310
  onBrokenLinks: utils_validation_1.Joi.string()
252
311
  .equal('ignore', 'log', 'warn', 'throw')
@@ -289,9 +348,14 @@ exports.ConfigSchema = utils_validation_1.Joi.object({
289
348
  headTags: utils_validation_1.Joi.array()
290
349
  .items(utils_validation_1.Joi.object({
291
350
  tagName: utils_validation_1.Joi.string().required(),
292
- attributes: utils_validation_1.Joi.object()
293
- .pattern(/[\w-]+/, utils_validation_1.Joi.string())
294
- .required(),
351
+ attributes: utils_validation_1.Joi.object().when('customElement', {
352
+ is: utils_validation_1.Joi.valid(true),
353
+ then: utils_validation_1.Joi.optional(),
354
+ otherwise: utils_validation_1.Joi.object()
355
+ .pattern(/[\w-]+/, utils_validation_1.Joi.string())
356
+ .required(),
357
+ }),
358
+ customElement: utils_validation_1.Joi.bool().default(false),
295
359
  }).unknown())
296
360
  .messages({
297
361
  'array.includes': '{#label} is invalid. A headTag must be an object with at least a "tagName" and an "attributes" property.',
@@ -328,11 +392,14 @@ exports.ConfigSchema = utils_validation_1.Joi.object({
328
392
  .arity(1)
329
393
  .optional()
330
394
  .default(() => exports.DEFAULT_CONFIG.markdown.preprocessor),
395
+ // Individual boolean defaults are not set here on purpose
396
+ // They are resolved in postProcessDocusaurusConfig based on
397
+ // the future.v4.mdx1CompatDisabledByDefault flag
331
398
  mdx1Compat: utils_validation_1.Joi.object({
332
- comments: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.markdown.mdx1Compat.comments),
333
- admonitions: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.markdown.mdx1Compat.admonitions),
334
- headingIds: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.markdown.mdx1Compat.headingIds),
335
- }).default(exports.DEFAULT_CONFIG.markdown.mdx1Compat),
399
+ comments: utils_validation_1.Joi.boolean(),
400
+ admonitions: utils_validation_1.Joi.boolean(),
401
+ headingIds: utils_validation_1.Joi.boolean(),
402
+ }).default({}),
336
403
  remarkRehypeOptions:
337
404
  // add proper external options validation?
338
405
  // Not sure if it's a good idea, validation is likely to become stale
@@ -349,13 +416,43 @@ exports.ConfigSchema = utils_validation_1.Joi.object({
349
416
  .try(utils_validation_1.Joi.string().equal('ignore', 'log', 'warn', 'throw'), utils_validation_1.Joi.function())
350
417
  .default(exports.DEFAULT_CONFIG.markdown.hooks.onBrokenMarkdownImages),
351
418
  }).default(exports.DEFAULT_CONFIG.markdown.hooks),
352
- }).default(exports.DEFAULT_CONFIG.markdown),
419
+ }).default({
420
+ ...exports.DEFAULT_CONFIG.markdown,
421
+ mdx1Compat: {
422
+ // erased on purpose, filled using postprocessing
423
+ },
424
+ }),
353
425
  }).messages({
354
426
  'docusaurus.configValidationWarning': 'Docusaurus config validation warning. Field {#label}: {#warningMessage}',
355
427
  });
356
428
  // Expressing this kind of logic in Joi is a pain
357
429
  // We also want to decouple logic from Joi: easier to remove it later!
358
430
  function postProcessDocusaurusConfig(config) {
431
+ var _a;
432
+ // Resolve storage.namespace based on the v4 future flag
433
+ // undefined means "not explicitly set by user"
434
+ if (config.storage.namespace === undefined) {
435
+ config.storage.namespace = config.future.v4.siteStorageNamespacing;
436
+ }
437
+ // Resolve faster config based on the v4.fasterByDefault flag
438
+ // undefined means "not explicitly set by user"
439
+ if (config.future.faster === undefined) {
440
+ config.future.faster = {};
441
+ }
442
+ const fasterDefault = config.future.v4.fasterByDefault;
443
+ const fasterKeys = Object.keys(exports.DEFAULT_FASTER_CONFIG);
444
+ for (const key of fasterKeys) {
445
+ if (config.future.faster[key] === undefined) {
446
+ config.future.faster[key] = fasterDefault;
447
+ }
448
+ }
449
+ // Resolve mdx1Compat config based on the v4.mdx1CompatDisabledByDefault flag
450
+ // undefined means "not explicitly set by user"
451
+ const mdx1CompatDefault = !config.future.v4.mdx1CompatDisabledByDefault;
452
+ const mdx1CompatKeys = Object.keys(exports.DEFAULT_MARKDOWN_MDX1COMPAT);
453
+ for (const key of mdx1CompatKeys) {
454
+ (_a = config.markdown.mdx1Compat)[key] ?? (_a[key] = mdx1CompatDefault);
455
+ }
359
456
  if (config.onBrokenMarkdownLinks) {
360
457
  logger_1.default.warn `The code=${'siteConfig.onBrokenMarkdownLinks'} config option is deprecated and will be removed in Docusaurus v4.
361
458
  Please migrate and move this option to code=${'siteConfig.markdown.hooks.onBrokenMarkdownLinks'} instead.`;
@@ -364,15 +461,24 @@ Please migrate and move this option to code=${'siteConfig.markdown.hooks.onBroke
364
461
  // We erase the former one to ensure we don't use it anywhere
365
462
  config.onBrokenMarkdownLinks = undefined;
366
463
  }
367
- if (config.future.experimental_faster.ssgWorkerThreads &&
464
+ // We normalize the VCS config when using a boolean value
465
+ if (typeof config.future.experimental_vcs === 'boolean') {
466
+ const vcsConfig = config.future.experimental_vcs
467
+ ? config.future.faster.gitEagerVcs
468
+ ? (0, utils_1.getVcsPreset)('default-v2')
469
+ : (0, utils_1.getVcsPreset)('default-v1')
470
+ : (0, utils_1.getVcsPreset)('disabled');
471
+ config.future.experimental_vcs = vcsConfig;
472
+ }
473
+ if (config.future.faster.ssgWorkerThreads &&
368
474
  !config.future.v4.removeLegacyPostBuildHeadAttribute) {
369
- throw new Error(`Docusaurus config ${logger_1.default.code('future.experimental_faster.ssgWorkerThreads')} requires the future flag ${logger_1.default.code('future.v4.removeLegacyPostBuildHeadAttribute')} to be turned on.
475
+ throw new Error(`Docusaurus config ${logger_1.default.code('future.faster.ssgWorkerThreads')} requires the future flag ${logger_1.default.code('future.v4.removeLegacyPostBuildHeadAttribute')} to be turned on.
370
476
  If you use Docusaurus Faster, we recommend that you also activate Docusaurus v4 future flags: ${logger_1.default.code('{future: {v4: true}}')}
371
477
  All the v4 future flags are documented here: https://docusaurus.io/docs/api/docusaurus-config#future`);
372
478
  }
373
- if (config.future.experimental_faster.rspackPersistentCache &&
374
- !config.future.experimental_faster.rspackBundler) {
375
- throw new Error(`Docusaurus config flag ${logger_1.default.code('future.experimental_faster.rspackPersistentCache')} requires the flag ${logger_1.default.code('future.experimental_faster.rspackBundler')} to be turned on.`);
479
+ if (config.future.faster.rspackPersistentCache &&
480
+ !config.future.faster.rspackBundler) {
481
+ throw new Error(`Docusaurus config flag ${logger_1.default.code('future.faster.rspackPersistentCache')} requires the flag ${logger_1.default.code('future.faster.rspackBundler')} to be turned on.`);
376
482
  }
377
483
  }
378
484
  // TODO move to @docusaurus/utils-validation
@@ -12,15 +12,18 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
12
12
  const html_tags_1 = tslib_1.__importDefault(require("html-tags"));
13
13
  const void_1 = tslib_1.__importDefault(require("html-tags/void"));
14
14
  const escape_html_1 = tslib_1.__importDefault(require("escape-html"));
15
+ // TODO this should be done at config validation time, not here
15
16
  function assertIsHtmlTagObject(val) {
16
17
  if (typeof val !== 'object' || !val) {
17
18
  throw new Error(`"${val}" is not a valid HTML tag object.`);
18
19
  }
19
- if (typeof val.tagName !== 'string') {
20
+ const htmlTag = val;
21
+ if (typeof htmlTag.tagName !== 'string') {
20
22
  throw new Error(`${JSON.stringify(val)} is not a valid HTML tag object. "tagName" must be defined as a string.`);
21
23
  }
22
- if (!html_tags_1.default.includes(val.tagName)) {
23
- throw new Error(`Error loading ${JSON.stringify(val)}, "${val.tagName}" is not a valid HTML tag.`);
24
+ if (!htmlTag.customElement &&
25
+ !html_tags_1.default.includes(htmlTag.tagName)) {
26
+ throw new Error(`Error loading ${JSON.stringify(val)}, "${htmlTag.tagName}" is not a valid HTML tag. Either use a valid "tagName" or set "customElement: true".`);
24
27
  }
25
28
  }
26
29
  function hashRouterAbsoluteToRelativeTagAttribute(name, value) {
@@ -4,8 +4,12 @@
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 { I18n, DocusaurusConfig, I18nLocaleConfig } from '@docusaurus/types';
7
+ import type { I18n, DocusaurusConfig, I18nLocaleConfig, I18nConfig } from '@docusaurus/types';
8
8
  export declare function getDefaultLocaleConfig(locale: string): Omit<I18nLocaleConfig, 'translate' | 'url' | 'baseUrl'>;
9
+ export declare function getLocaleList({ i18nConfig, currentLocale, }: {
10
+ i18nConfig: I18nConfig;
11
+ currentLocale: string;
12
+ }): [string, ...string[]];
9
13
  export declare function loadI18n({ siteDir, config, currentLocale, automaticBaseUrlLocalizationDisabled, }: {
10
14
  siteDir: string;
11
15
  config: DocusaurusConfig;
@@ -7,6 +7,7 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.getDefaultLocaleConfig = getDefaultLocaleConfig;
10
+ exports.getLocaleList = getLocaleList;
10
11
  exports.loadI18n = loadI18n;
11
12
  const tslib_1 = require("tslib");
12
13
  const path_1 = tslib_1.__importDefault(require("path"));
@@ -51,9 +52,7 @@ function getDefaultCalendar(localeStr) {
51
52
  // Not well-supported but server code can infer a calendar from the locale
52
53
  // See https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getCalendars
53
54
  // See https://caniuse.com/mdn-javascript_builtins_intl_locale_getcalendars
54
- const calendars =
55
- // @ts-expect-error: new std method (Bun/JSC/WebKit)
56
- locale.getCalendars?.() ??
55
+ const calendars = locale.getCalendars?.() ??
57
56
  // @ts-expect-error: non-std attribute (V8/Chromium/Node)
58
57
  locale.calendars;
59
58
  if (calendars instanceof Array && calendars[0]) {
@@ -69,7 +68,7 @@ function getDefaultDirection(localeStr) {
69
68
  // TODO Docusaurus v4: remove the fallback to locale.textInfo
70
69
  // @ts-expect-error: The TC39 proposal was updated
71
70
  const textInto = locale.getTextInfo?.() ?? locale.textInfo;
72
- return textInto.direction;
71
+ return textInto.direction ?? 'ltr';
73
72
  }
74
73
  function getDefaultLocaleConfig(locale) {
75
74
  try {
@@ -82,22 +81,29 @@ function getDefaultLocaleConfig(locale) {
82
81
  };
83
82
  }
84
83
  catch (e) {
85
- throw new Error(`Docusaurus couldn't get default locale config for ${locale}`, { cause: e });
84
+ throw new Error(`Docusaurus couldn't infer a default locale config for ${logger_1.default.name(locale)}.
85
+ Make sure it is a valid BCP 47 locale name (e.g. en, fr, fr-FR, etc.) and/or provide a valid BCP 47 ${logger_1.default.code(`siteConfig.i18n.localeConfig['${locale}'].htmlLang`)} attribute.`, { cause: e });
86
86
  }
87
87
  }
88
- async function loadI18n({ siteDir, config, currentLocale, automaticBaseUrlLocalizationDisabled, }) {
89
- const { i18n: i18nConfig } = config;
88
+ function getLocaleList({ i18nConfig, currentLocale, }) {
90
89
  if (!i18nConfig.locales.includes(currentLocale)) {
91
- logger_1.default.warn `The locale name=${currentLocale} was not found in your site configuration: Available locales are: ${i18nConfig.locales}
92
- Note: Docusaurus only support running one locale at a time.`;
90
+ logger_1.default.warn `The locale name=${currentLocale} was not found in your Docusaurus site configuration.
91
+ We recommend adding the name=${currentLocale} to your site i18n config, but we will still try to run your site.
92
+ Declared site config locales are: ${i18nConfig.locales}`;
93
+ return i18nConfig.locales.concat(currentLocale);
93
94
  }
94
- const locales = i18nConfig.locales.includes(currentLocale)
95
- ? i18nConfig.locales
96
- : i18nConfig.locales.concat(currentLocale);
95
+ return i18nConfig.locales;
96
+ }
97
+ async function loadI18n({ siteDir, config, currentLocale, automaticBaseUrlLocalizationDisabled, }) {
98
+ const { i18n: i18nConfig } = config;
99
+ const locales = getLocaleList({
100
+ i18nConfig,
101
+ currentLocale,
102
+ });
97
103
  async function getFullLocaleConfig(locale) {
98
104
  const localeConfigInput = i18nConfig.localeConfigs[locale] ?? {};
99
105
  const localeConfig = {
100
- ...getDefaultLocaleConfig(locale),
106
+ ...getDefaultLocaleConfig(localeConfigInput.htmlLang ?? locale),
101
107
  ...localeConfigInput,
102
108
  };
103
109
  // By default, translations will be enabled if i18n/<locale> dir exists
@@ -60,7 +60,7 @@ function createBootstrapPlugin({ siteDir, siteConfig, }) {
60
60
  */
61
61
  async function createMDXFallbackPlugin({ siteDir, siteConfig, }) {
62
62
  const mdxLoaderItem = await (0, mdx_loader_1.createMDXLoaderItem)({
63
- useCrossCompilerCache: siteConfig.future.experimental_faster.mdxCrossCompilerCache,
63
+ useCrossCompilerCache: siteConfig.future.faster.mdxCrossCompilerCache,
64
64
  admonitions: true,
65
65
  staticDirs: siteConfig.staticDirectories.map((dir) => path_1.default.resolve(siteDir, dir)),
66
66
  siteDir,
@@ -43,6 +43,14 @@ async function loadContext(params) {
43
43
  customConfigFilePath,
44
44
  }),
45
45
  });
46
+ // Not sure where is the best place to put this VCS initialization call?
47
+ // The sooner is probably the better
48
+ // Note: we don't await the result on purpose!
49
+ // VCS initialization can be slow for large repos, and we don't want to block
50
+ // VCS integrations should be carefully designed to avoid blocking
51
+ logger_1.PerfLogger.async('VCS init', () => {
52
+ return initialSiteConfig.future.experimental_vcs.initialize({ siteDir });
53
+ });
46
54
  const currentBundler = await (0, bundler_1.getCurrentBundler)({
47
55
  siteConfig: initialSiteConfig,
48
56
  });
@@ -15,7 +15,7 @@ const babel_1 = require("@docusaurus/babel");
15
15
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
16
16
  const uselessBabelConfigMessages = async ({ site }) => {
17
17
  const { props: { siteDir, siteConfig }, } = site;
18
- if (siteConfig.future.experimental_faster.swcJsLoader) {
18
+ if (siteConfig.future.faster.swcJsLoader) {
19
19
  const babelConfigFilePath = await (0, babel_1.getCustomBabelConfigFilePath)(siteDir);
20
20
  if (babelConfigFilePath) {
21
21
  return [
@@ -5,9 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { DocusaurusConfig, SiteStorage } from '@docusaurus/types';
8
- type PartialFuture = Pick<DocusaurusConfig['future'], 'experimental_storage'>;
9
- type PartialConfig = Pick<DocusaurusConfig, 'url' | 'baseUrl'> & {
10
- future: PartialFuture;
11
- };
8
+ type PartialConfig = Pick<DocusaurusConfig, 'url' | 'baseUrl' | 'storage'>;
12
9
  export declare function createSiteStorage(config: PartialConfig): SiteStorage;
13
10
  export {};
@@ -14,18 +14,18 @@ function automaticNamespace(config) {
14
14
  return (0, utils_1.simpleHash)(normalizedUrl, 3);
15
15
  }
16
16
  function getNamespaceString(config) {
17
- if (config.future.experimental_storage.namespace === true) {
17
+ if (config.storage.namespace === true) {
18
18
  return automaticNamespace(config);
19
19
  }
20
- else if (config.future.experimental_storage.namespace === false) {
20
+ else if (config.storage.namespace === false) {
21
21
  return null;
22
22
  }
23
23
  else {
24
- return config.future.experimental_storage.namespace;
24
+ return config.storage.namespace;
25
25
  }
26
26
  }
27
27
  function createSiteStorage(config) {
28
- const { type } = config.future.experimental_storage;
28
+ const { type } = config.storage;
29
29
  const namespaceString = getNamespaceString(config);
30
30
  const namespace = namespaceString ? `-${namespaceString}` : '';
31
31
  return {
@@ -136,8 +136,7 @@ async function executeSSG({ props, serverBundlePath, clientManifestPath, router,
136
136
  logger_1.PerfLogger.end('Generate Hash Router entry point');
137
137
  return { collectedData: {} };
138
138
  }
139
- const createExecutor = props.siteConfig.future.experimental_faster
140
- .ssgWorkerThreads
139
+ const createExecutor = props.siteConfig.future.faster.ssgWorkerThreads
141
140
  ? createPooledSSGExecutor
142
141
  : createSimpleSSGExecutor;
143
142
  const executor = await createExecutor({ params, pathnames: props.routesPaths });
@@ -26,8 +26,7 @@ async function createSSGParams({ props, serverBundlePath, clientManifestPath, })
26
26
  noIndex: props.siteConfig.noIndex,
27
27
  DOCUSAURUS_VERSION: utils_1.DOCUSAURUS_VERSION,
28
28
  serverBundlePath,
29
- htmlMinifierType: props.siteConfig.future.experimental_faster
30
- .swcHtmlMinimizer
29
+ htmlMinifierType: props.siteConfig.future.faster.swcHtmlMinimizer
31
30
  ? 'swc'
32
31
  : 'terser',
33
32
  v4RemoveLegacyPostBuildHeadAttribute: props.siteConfig.future.v4.removeLegacyPostBuildHeadAttribute,
@@ -39,6 +39,13 @@ async function createAliasesForTheme(themePath, addOriginalAlias) {
39
39
  }
40
40
  const themeComponentFiles = await (0, utils_1.Globby)(['**/*.{js,jsx,ts,tsx}'], {
41
41
  cwd: themePath,
42
+ ignore: [
43
+ // Ignore co-located test files
44
+ '**/__tests__/**',
45
+ '**/*.test.{js,jsx,ts,tsx}',
46
+ // Ignore type declaration files
47
+ '**/*.d.ts',
48
+ ],
42
49
  });
43
50
  const aliases = {};
44
51
  themeComponentFiles.forEach((relativeSource) => {
@@ -86,7 +86,7 @@ async function createBaseConfig({ props, isServer, minify, faster, configureWebp
86
86
  return disabledPersistentCacheValue;
87
87
  }
88
88
  if (props.currentBundler.name === 'rspack') {
89
- if (props.siteConfig.future.experimental_faster.rspackPersistentCache) {
89
+ if (props.siteConfig.future.faster.rspackPersistentCache) {
90
90
  // Use cache: true + experiments.cache.type: "persistent"
91
91
  // See https://rspack.dev/config/experiments#persistent-cache
92
92
  return true;
@@ -118,24 +118,6 @@ async function createBaseConfig({ props, isServer, minify, faster, configureWebp
118
118
  buildDependencies: getCacheBuildDependencies(),
119
119
  };
120
120
  }
121
- if (process.env.DISABLE_RSPACK_INCREMENTAL) {
122
- // Enabled by default since Rspack 1.4
123
- console.log('Rspack incremental disabled');
124
- experiments.incremental = false;
125
- }
126
- // See https://rspack.rs/blog/announcing-1-5#barrel-file-optimization
127
- if (process.env.DISABLE_RSPACK_LAZY_BARREL) {
128
- console.log('Rspack lazyBarrel disabled');
129
- experiments.lazyBarrel = false;
130
- }
131
- else {
132
- // TODO remove after we upgrade to Rspack 1.6+
133
- // Enabled by default for Rspack >= 1.6
134
- experiments.lazyBarrel = true;
135
- }
136
- // TODO re-enable later, there's an Rspack performance issue
137
- // see https://github.com/facebook/docusaurus/pull/11178
138
- experiments.parallelCodeSplitting = false;
139
121
  return experiments;
140
122
  }
141
123
  return undefined;
@@ -18,7 +18,7 @@ async function createServerConfig({ props, configureWebpackUtils, }) {
18
18
  props,
19
19
  isServer: true,
20
20
  minify: false,
21
- faster: props.siteConfig.future.experimental_faster,
21
+ faster: props.siteConfig.future.faster,
22
22
  configureWebpackUtils,
23
23
  });
24
24
  const ProgressBarPlugin = await (0, bundler_1.getProgressBarPlugin)({
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": "3.9.2",
4
+ "version": "3.10.0",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -33,13 +33,13 @@
33
33
  "url": "https://github.com/facebook/docusaurus/issues"
34
34
  },
35
35
  "dependencies": {
36
- "@docusaurus/babel": "3.9.2",
37
- "@docusaurus/bundler": "3.9.2",
38
- "@docusaurus/logger": "3.9.2",
39
- "@docusaurus/mdx-loader": "3.9.2",
40
- "@docusaurus/utils": "3.9.2",
41
- "@docusaurus/utils-common": "3.9.2",
42
- "@docusaurus/utils-validation": "3.9.2",
36
+ "@docusaurus/babel": "3.10.0",
37
+ "@docusaurus/bundler": "3.10.0",
38
+ "@docusaurus/logger": "3.10.0",
39
+ "@docusaurus/mdx-loader": "3.10.0",
40
+ "@docusaurus/utils": "3.10.0",
41
+ "@docusaurus/utils-common": "3.10.0",
42
+ "@docusaurus/utils-validation": "3.10.0",
43
43
  "boxen": "^6.2.1",
44
44
  "chalk": "^4.1.2",
45
45
  "chokidar": "^3.5.3",
@@ -51,7 +51,7 @@
51
51
  "escape-html": "^1.0.3",
52
52
  "eta": "^2.2.0",
53
53
  "eval": "^0.1.8",
54
- "execa": "5.1.1",
54
+ "execa": "^5.1.1",
55
55
  "fs-extra": "^11.1.1",
56
56
  "html-tags": "^3.3.1",
57
57
  "html-webpack-plugin": "^5.6.0",
@@ -62,12 +62,12 @@
62
62
  "prompts": "^2.4.2",
63
63
  "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0",
64
64
  "react-loadable": "npm:@docusaurus/react-loadable@6.0.0",
65
- "react-loadable-ssr-addon-v5-slorber": "^1.0.1",
65
+ "react-loadable-ssr-addon-v5-slorber": "^1.0.3",
66
66
  "react-router": "^5.3.4",
67
67
  "react-router-config": "^5.1.1",
68
68
  "react-router-dom": "^5.3.4",
69
69
  "semver": "^7.5.4",
70
- "serve-handler": "^6.1.6",
70
+ "serve-handler": "^6.1.7",
71
71
  "tinypool": "^1.0.2",
72
72
  "tslib": "^2.6.0",
73
73
  "update-notifier": "^6.0.2",
@@ -77,26 +77,32 @@
77
77
  "webpack-merge": "^6.0.1"
78
78
  },
79
79
  "devDependencies": {
80
- "@docusaurus/module-type-aliases": "3.9.2",
81
- "@docusaurus/types": "3.9.2",
80
+ "@docusaurus/module-type-aliases": "3.10.0",
81
+ "@docusaurus/types": "3.10.0",
82
82
  "@total-typescript/shoehorn": "^0.1.2",
83
83
  "@types/detect-port": "^1.3.3",
84
- "@types/react-dom": "^18.2.7",
84
+ "@types/react-dom": "^19.2.3",
85
85
  "@types/react-router-config": "^5.0.7",
86
86
  "@types/serve-handler": "^6.1.4",
87
87
  "@types/update-notifier": "^6.0.4",
88
88
  "@types/webpack-bundle-analyzer": "^4.7.0",
89
- "react-test-renderer": "^18.0.0",
89
+ "@types/webpack-env": "^1.18.8",
90
90
  "tmp-promise": "^3.0.3",
91
91
  "tree-node-cli": "^1.6.0"
92
92
  },
93
93
  "peerDependencies": {
94
+ "@docusaurus/faster": "*",
94
95
  "@mdx-js/react": "^3.0.0",
95
96
  "react": "^18.0.0 || ^19.0.0",
96
97
  "react-dom": "^18.0.0 || ^19.0.0"
97
98
  },
99
+ "peerDependenciesMeta": {
100
+ "@docusaurus/faster": {
101
+ "optional": true
102
+ }
103
+ },
98
104
  "engines": {
99
105
  "node": ">=20.0"
100
106
  },
101
- "gitHead": "abfbe5621b08407bc3dcbe6111ff118d4c22f7a1"
107
+ "gitHead": "0d98888a7645a5fb1330c905b75faf868f829f5c"
102
108
  }