@docusaurus/core
Version:
Easy to Maintain Open Source Documentation Websites
508 lines (507 loc) • 24.8 kB
JavaScript
;
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
Object.defineProperty(exports, "__esModule", { value: true });
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;
exports.validateConfig = validateConfig;
const tslib_1 = require("tslib");
const utils_1 = require("@docusaurus/utils");
const utils_validation_1 = require("@docusaurus/utils-validation");
const utils_common_1 = require("@docusaurus/utils-common");
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
const DEFAULT_I18N_LOCALE = 'en';
const SiteUrlSchema = utils_validation_1.Joi.string()
.custom((value, helpers) => {
try {
const { pathname } = new URL(value);
if (pathname !== '/') {
return helpers.error('docusaurus.subPathError', { pathname });
}
}
catch {
return helpers.error('any.invalid');
}
return (0, utils_common_1.removeTrailingSlash)(value);
})
.messages({
'any.invalid': '"{#value}" does not look like a valid URL. Make sure it has a protocol; for example, "https://example.com".',
'docusaurus.subPathError': 'The url is not supposed to contain a sub-path like "{#pathname}". Please use the baseUrl field for sub-paths.',
});
const BaseUrlSchema = utils_validation_1.Joi
// Weird Joi trick needed, otherwise value '' is not normalized...
.alternatives()
.try(utils_validation_1.Joi.string().required().allow(''))
.custom((value) => (0, utils_common_1.addLeadingSlash)((0, utils_common_1.addTrailingSlash)(value)));
exports.DEFAULT_I18N_CONFIG = {
defaultLocale: DEFAULT_I18N_LOCALE,
path: utils_1.DEFAULT_I18N_DIR_NAME,
locales: [DEFAULT_I18N_LOCALE],
localeConfigs: {},
};
exports.DEFAULT_STORAGE_CONFIG = {
type: 'localStorage',
namespace: false,
};
exports.DEFAULT_FASTER_CONFIG = {
swcJsLoader: false,
swcJsMinimizer: false,
swcHtmlMinimizer: false,
lightningCssMinimizer: false,
mdxCrossCompilerCache: false,
rspackBundler: false,
rspackPersistentCache: false,
ssgWorkerThreads: false,
gitEagerVcs: false,
};
// When using the "faster: true" shortcut
exports.DEFAULT_FASTER_CONFIG_TRUE = {
swcJsLoader: true,
swcJsMinimizer: true,
swcHtmlMinimizer: true,
lightningCssMinimizer: true,
mdxCrossCompilerCache: true,
rspackBundler: true,
rspackPersistentCache: true,
ssgWorkerThreads: true,
gitEagerVcs: true,
};
exports.DEFAULT_FUTURE_V4_CONFIG = {
removeLegacyPostBuildHeadAttribute: false,
useCssCascadeLayers: false,
siteStorageNamespacing: false,
fasterByDefault: false,
mdx1CompatDisabledByDefault: false,
};
// When using the "v4: true" shortcut
exports.DEFAULT_FUTURE_V4_CONFIG_TRUE = {
removeLegacyPostBuildHeadAttribute: true,
useCssCascadeLayers: true,
siteStorageNamespacing: true,
fasterByDefault: true,
mdx1CompatDisabledByDefault: true,
};
exports.DEFAULT_FUTURE_CONFIG = {
v4: exports.DEFAULT_FUTURE_V4_CONFIG,
faster: exports.DEFAULT_FASTER_CONFIG,
experimental_vcs: (0, utils_1.getVcsPreset)('default-v1'),
experimental_router: 'browser',
};
exports.DEFAULT_MARKDOWN_HOOKS = {
onBrokenMarkdownLinks: 'warn',
onBrokenMarkdownImages: 'throw',
};
exports.DEFAULT_MARKDOWN_MDX1COMPAT = {
comments: true,
admonitions: true,
headingIds: true,
};
exports.DEFAULT_MARKDOWN_CONFIG = {
// TODO Docusaurus v5: change this to "detect"?
// we probably need stable CommonMark support first
// see https://github.com/facebook/docusaurus/issues/9092
format: 'mdx',
mermaid: false,
emoji: true,
preprocessor: undefined,
parseFrontMatter: utils_1.DEFAULT_PARSE_FRONT_MATTER,
mdx1Compat: exports.DEFAULT_MARKDOWN_MDX1COMPAT,
anchors: {
maintainCase: false,
},
remarkRehypeOptions: undefined,
hooks: exports.DEFAULT_MARKDOWN_HOOKS,
};
exports.DEFAULT_CONFIG = {
i18n: exports.DEFAULT_I18N_CONFIG,
storage: exports.DEFAULT_STORAGE_CONFIG,
future: exports.DEFAULT_FUTURE_CONFIG,
onBrokenLinks: 'throw',
onBrokenAnchors: 'warn', // TODO Docusaurus v4: change to throw
onBrokenMarkdownLinks: undefined,
onDuplicateRoutes: 'warn',
plugins: [],
themes: [],
presets: [],
headTags: [],
stylesheets: [],
scripts: [],
clientModules: [],
customFields: {},
themeConfig: {},
titleDelimiter: '|',
noIndex: false,
tagline: '',
baseUrlIssueBanner: true,
staticDirectories: [utils_1.DEFAULT_STATIC_DIR_NAME],
markdown: exports.DEFAULT_MARKDOWN_CONFIG,
};
function createPluginSchema(theme) {
return utils_validation_1.Joi.alternatives()
.try(utils_validation_1.Joi.function(), utils_validation_1.Joi.array()
.ordered(utils_validation_1.Joi.function().required(), utils_validation_1.Joi.object().required())
.length(2), utils_validation_1.Joi.string(), utils_validation_1.Joi.array()
.ordered(utils_validation_1.Joi.string().required(), utils_validation_1.Joi.object().required())
.length(2), utils_validation_1.Joi.any().valid(false, null))
.error((errors) => {
errors.forEach((error) => {
const validConfigExample = theme
? `Example valid theme config:
{
themes: [
["@docusaurus/theme-classic",options],
"./myTheme",
["./myTheme",{someOption: 42}],
function myTheme() { },
[function myTheme() { },options]
],
};`
: `Example valid plugin config:
{
plugins: [
["@docusaurus/plugin-content-docs",options],
"./myPlugin",
["./myPlugin",{someOption: 42}],
function myPlugin() { },
[function myPlugin() { },options]
],
};`;
error.message = ` => Bad Docusaurus ${theme ? 'theme' : 'plugin'} value ${error.path.reduce((acc, cur) => typeof cur === 'string' ? `${acc}.${cur}` : `${acc}[${cur}]`)}.
${validConfigExample}
`;
});
return errors;
});
}
const PluginSchema = createPluginSchema(false);
const ThemeSchema = createPluginSchema(true);
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), utils_validation_1.Joi.any().valid(false, null))
.messages({
'alternatives.types': `{#label} does not look like a valid preset config. A preset config entry should be one of:
- A tuple of [presetName, options], like \`["classic", \\{ blog: false \\}]\`, or
- A simple string, like \`"classic"\``,
});
const LocaleConfigSchema = utils_validation_1.Joi.object({
label: utils_validation_1.Joi.string(),
htmlLang: utils_validation_1.Joi.string(),
direction: utils_validation_1.Joi.string().equal('ltr', 'rtl'),
calendar: utils_validation_1.Joi.string(),
path: utils_validation_1.Joi.string(),
translate: utils_validation_1.Joi.boolean(),
url: SiteUrlSchema,
baseUrl: BaseUrlSchema,
});
const I18N_CONFIG_SCHEMA = utils_validation_1.Joi.object({
defaultLocale: utils_validation_1.Joi.string().required(),
path: utils_validation_1.Joi.string().default(exports.DEFAULT_I18N_CONFIG.path),
locales: utils_validation_1.Joi.array().items().min(1).items(utils_validation_1.Joi.string().required()).required(),
localeConfigs: utils_validation_1.Joi.object()
.pattern(/.*/, LocaleConfigSchema)
.default(exports.DEFAULT_I18N_CONFIG.localeConfigs),
})
.optional()
.default(exports.DEFAULT_I18N_CONFIG);
// Individual boolean defaults are not set here on purpose
// They are resolved in postProcessDocusaurusConfig based on
// the future.v4.fasterByDefault flag
const FASTER_CONFIG_SCHEMA = utils_validation_1.Joi.alternatives()
.try(utils_validation_1.Joi.object({
swcJsLoader: utils_validation_1.Joi.boolean(),
swcJsMinimizer: utils_validation_1.Joi.boolean(),
swcHtmlMinimizer: utils_validation_1.Joi.boolean(),
lightningCssMinimizer: utils_validation_1.Joi.boolean(),
mdxCrossCompilerCache: utils_validation_1.Joi.boolean(),
rspackBundler: utils_validation_1.Joi.boolean(),
rspackPersistentCache: utils_validation_1.Joi.boolean(),
ssgWorkerThreads: utils_validation_1.Joi.boolean(),
gitEagerVcs: utils_validation_1.Joi.boolean(),
}), utils_validation_1.Joi.boolean()
.required()
.custom((bool) => bool ? exports.DEFAULT_FASTER_CONFIG_TRUE : exports.DEFAULT_FASTER_CONFIG))
.optional();
const FUTURE_V4_SCHEMA = utils_validation_1.Joi.alternatives()
.try(utils_validation_1.Joi.object({
removeLegacyPostBuildHeadAttribute: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.removeLegacyPostBuildHeadAttribute),
useCssCascadeLayers: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.useCssCascadeLayers),
siteStorageNamespacing: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.siteStorageNamespacing),
fasterByDefault: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.fasterByDefault),
mdx1CompatDisabledByDefault: utils_validation_1.Joi.boolean().default(exports.DEFAULT_FUTURE_V4_CONFIG.mdx1CompatDisabledByDefault),
}), utils_validation_1.Joi.boolean()
.required()
.custom((bool) => bool ? exports.DEFAULT_FUTURE_V4_CONFIG_TRUE : exports.DEFAULT_FUTURE_V4_CONFIG))
.optional()
.default(exports.DEFAULT_FUTURE_V4_CONFIG);
const STORAGE_CONFIG_SCHEMA = utils_validation_1.Joi.object({
type: utils_validation_1.Joi.string()
.equal('localStorage', 'sessionStorage')
.default(exports.DEFAULT_STORAGE_CONFIG.type),
// namespace default is not set here on purpose
// It is resolved in postProcessDocusaurusConfig based on
// the future.v4.siteStorageNamespacing flag
namespace: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.string(), utils_validation_1.Joi.boolean()),
})
.optional()
.default({ type: exports.DEFAULT_STORAGE_CONFIG.type });
const VCS_CONFIG_OBJECT_SCHEMA = utils_validation_1.Joi.object({
// All the fields are required on purpose
// You either provide a full VCS config or nothing
initialize: utils_validation_1.Joi.function().maxArity(1).required(),
getFileCreationInfo: utils_validation_1.Joi.function().arity(1).required(),
getFileLastUpdateInfo: utils_validation_1.Joi.function().arity(1).required(),
});
const VCS_CONFIG_SCHEMA = utils_validation_1.Joi.custom((input) => {
if (typeof input === 'string') {
const presetName = input;
if (!utils_1.VcsPresetNames.includes(presetName)) {
throw new Error(`VCS config preset name '${input}' is not valid.`);
}
return (0, utils_1.getVcsPreset)(presetName);
}
if (typeof input === 'boolean') {
// We return the boolean on purpose
// We'll normalize it to a real VcsConfig later
// This is annoying, but we have to read the future flag to switch to the
// new "default-v2" config (not easy to do it here)
return input;
}
const { error, value } = VCS_CONFIG_OBJECT_SCHEMA.validate(input);
if (error) {
throw error;
}
return value;
}).default(true);
const FUTURE_CONFIG_SCHEMA = utils_validation_1.Joi.object({
v4: FUTURE_V4_SCHEMA,
faster: FASTER_CONFIG_SCHEMA,
experimental_vcs: VCS_CONFIG_SCHEMA,
experimental_router: utils_validation_1.Joi.string()
.equal('browser', 'hash')
.default(exports.DEFAULT_FUTURE_CONFIG.experimental_router),
experimental_storage: utils_validation_1.Joi.any()
.forbidden()
.messages({
'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.`,
}),
experimental_faster: utils_validation_1.Joi.any()
.forbidden()
.messages({
'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.`,
}),
})
.optional()
.default(exports.DEFAULT_FUTURE_CONFIG);
// TODO move to @docusaurus/utils-validation
exports.ConfigSchema = utils_validation_1.Joi.object({
url: SiteUrlSchema.required(),
baseUrl: BaseUrlSchema.required(),
baseUrlIssueBanner: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.baseUrlIssueBanner),
favicon: utils_validation_1.Joi.string().optional(),
title: utils_validation_1.Joi.string().required(),
trailingSlash: utils_validation_1.Joi.boolean(), // No default value! undefined = retrocompatible legacy behavior!
i18n: I18N_CONFIG_SCHEMA,
storage: STORAGE_CONFIG_SCHEMA,
future: FUTURE_CONFIG_SCHEMA,
onBrokenLinks: utils_validation_1.Joi.string()
.equal('ignore', 'log', 'warn', 'throw')
.default(exports.DEFAULT_CONFIG.onBrokenLinks),
onBrokenAnchors: utils_validation_1.Joi.string()
.equal('ignore', 'log', 'warn', 'throw')
.default(exports.DEFAULT_CONFIG.onBrokenAnchors),
onBrokenMarkdownLinks: utils_validation_1.Joi.string()
.equal('ignore', 'log', 'warn', 'throw')
.default(() => exports.DEFAULT_CONFIG.onBrokenMarkdownLinks),
onDuplicateRoutes: utils_validation_1.Joi.string()
.equal('ignore', 'log', 'warn', 'throw')
.default(exports.DEFAULT_CONFIG.onDuplicateRoutes),
organizationName: utils_validation_1.Joi.string().allow(''),
staticDirectories: utils_validation_1.Joi.array()
.items(utils_validation_1.Joi.string())
.default(exports.DEFAULT_CONFIG.staticDirectories),
projectName: utils_validation_1.Joi.string().allow(''),
deploymentBranch: utils_validation_1.Joi.string().optional(),
customFields: utils_validation_1.Joi.object().unknown().default(exports.DEFAULT_CONFIG.customFields),
githubHost: utils_validation_1.Joi.string(),
githubPort: utils_validation_1.Joi.string(),
plugins: utils_validation_1.Joi.array().items(PluginSchema).default(exports.DEFAULT_CONFIG.plugins),
themes: utils_validation_1.Joi.array().items(ThemeSchema).default(exports.DEFAULT_CONFIG.themes),
presets: utils_validation_1.Joi.array().items(PresetSchema).default(exports.DEFAULT_CONFIG.presets),
themeConfig: utils_validation_1.Joi.object().unknown().default(exports.DEFAULT_CONFIG.themeConfig),
scripts: utils_validation_1.Joi.array()
.items(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
src: utils_validation_1.Joi.string().required(),
async: utils_validation_1.Joi.bool(),
defer: utils_validation_1.Joi.bool(),
})
// See https://github.com/facebook/docusaurus/issues/3378
.unknown())
.messages({
'array.includes': '{#label} is invalid. A script must be a plain string (the src), or an object with at least a "src" property.',
})
.default(exports.DEFAULT_CONFIG.scripts),
ssrTemplate: utils_validation_1.Joi.string(),
headTags: utils_validation_1.Joi.array()
.items(utils_validation_1.Joi.object({
tagName: utils_validation_1.Joi.string().required(),
attributes: utils_validation_1.Joi.object().when('customElement', {
is: utils_validation_1.Joi.valid(true),
then: utils_validation_1.Joi.optional(),
otherwise: utils_validation_1.Joi.object()
.pattern(/[\w-]+/, utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.string(), utils_validation_1.Joi.boolean()))
.required(),
}),
customElement: utils_validation_1.Joi.bool().default(false),
}).unknown())
.messages({
'array.includes': '{#label} is invalid. A headTag must be an object with at least a "tagName" and an "attributes" property.',
})
.default(exports.DEFAULT_CONFIG.headTags),
stylesheets: utils_validation_1.Joi.array()
.items(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
href: utils_validation_1.Joi.string().required(),
type: utils_validation_1.Joi.string(),
}).unknown())
.messages({
'array.includes': '{#label} is invalid. A stylesheet must be a plain string (the href), or an object with at least a "href" property.',
})
.default(exports.DEFAULT_CONFIG.stylesheets),
clientModules: utils_validation_1.Joi.array()
.items(utils_validation_1.Joi.string())
.default(exports.DEFAULT_CONFIG.clientModules),
tagline: utils_validation_1.Joi.string().allow('').default(exports.DEFAULT_CONFIG.tagline),
titleDelimiter: utils_validation_1.Joi.string().default(exports.DEFAULT_CONFIG.titleDelimiter),
noIndex: utils_validation_1.Joi.bool().default(exports.DEFAULT_CONFIG.noIndex),
webpack: utils_validation_1.Joi.object({
jsLoader: utils_validation_1.Joi.alternatives()
.try(utils_validation_1.Joi.string().equal('babel'), utils_validation_1.Joi.function())
.optional(),
}).optional(),
markdown: utils_validation_1.Joi.object({
format: utils_validation_1.Joi.string()
.equal('mdx', 'md', 'detect')
.default(exports.DEFAULT_CONFIG.markdown.format),
parseFrontMatter: utils_validation_1.Joi.function().default(() => exports.DEFAULT_CONFIG.markdown.parseFrontMatter),
mermaid: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.markdown.mermaid),
emoji: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.markdown.emoji),
preprocessor: utils_validation_1.Joi.function()
.arity(1)
.optional()
.default(() => exports.DEFAULT_CONFIG.markdown.preprocessor),
// Individual boolean defaults are not set here on purpose
// They are resolved in postProcessDocusaurusConfig based on
// the future.v4.mdx1CompatDisabledByDefault flag
mdx1Compat: utils_validation_1.Joi.object({
comments: utils_validation_1.Joi.boolean(),
admonitions: utils_validation_1.Joi.boolean(),
headingIds: utils_validation_1.Joi.boolean(),
}).default({}),
remarkRehypeOptions:
// add proper external options validation?
// Not sure if it's a good idea, validation is likely to become stale
// See https://github.com/remarkjs/remark-rehype#options
utils_validation_1.Joi.object().unknown(),
anchors: utils_validation_1.Joi.object({
maintainCase: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.markdown.anchors.maintainCase),
}).default(exports.DEFAULT_CONFIG.markdown.anchors),
hooks: utils_validation_1.Joi.object({
onBrokenMarkdownLinks: utils_validation_1.Joi.alternatives()
.try(utils_validation_1.Joi.string().equal('ignore', 'log', 'warn', 'throw'), utils_validation_1.Joi.function())
.default(exports.DEFAULT_CONFIG.markdown.hooks.onBrokenMarkdownLinks),
onBrokenMarkdownImages: utils_validation_1.Joi.alternatives()
.try(utils_validation_1.Joi.string().equal('ignore', 'log', 'warn', 'throw'), utils_validation_1.Joi.function())
.default(exports.DEFAULT_CONFIG.markdown.hooks.onBrokenMarkdownImages),
}).default(exports.DEFAULT_CONFIG.markdown.hooks),
}).default({
...exports.DEFAULT_CONFIG.markdown,
mdx1Compat: {
// erased on purpose, filled using postprocessing
},
}),
}).messages({
'docusaurus.configValidationWarning': 'Docusaurus config validation warning. Field {#label}: {#warningMessage}',
});
// Expressing this kind of logic in Joi is a pain
// We also want to decouple logic from Joi: easier to remove it later!
function postProcessDocusaurusConfig(config) {
var _a;
// Resolve storage.namespace based on the v4 future flag
// undefined means "not explicitly set by user"
if (config.storage.namespace === undefined) {
config.storage.namespace = config.future.v4.siteStorageNamespacing;
}
// Resolve faster config based on the v4.fasterByDefault flag
// undefined means "not explicitly set by user"
if (config.future.faster === undefined) {
config.future.faster = {};
}
const fasterDefault = config.future.v4.fasterByDefault;
const fasterKeys = Object.keys(exports.DEFAULT_FASTER_CONFIG);
for (const key of fasterKeys) {
if (config.future.faster[key] === undefined) {
config.future.faster[key] = fasterDefault;
}
}
// Resolve mdx1Compat config based on the v4.mdx1CompatDisabledByDefault flag
// undefined means "not explicitly set by user"
const mdx1CompatDefault = !config.future.v4.mdx1CompatDisabledByDefault;
const mdx1CompatKeys = Object.keys(exports.DEFAULT_MARKDOWN_MDX1COMPAT);
for (const key of mdx1CompatKeys) {
(_a = config.markdown.mdx1Compat)[key] ?? (_a[key] = mdx1CompatDefault);
}
if (config.onBrokenMarkdownLinks) {
logger_1.default.warn `The code=${'siteConfig.onBrokenMarkdownLinks'} config option is deprecated and will be removed in Docusaurus v4.
Please migrate and move this option to code=${'siteConfig.markdown.hooks.onBrokenMarkdownLinks'} instead.`;
// For v3 retro compatibility we use the old attribute over the new one
config.markdown.hooks.onBrokenMarkdownLinks = config.onBrokenMarkdownLinks;
// We erase the former one to ensure we don't use it anywhere
config.onBrokenMarkdownLinks = undefined;
}
// We normalize the VCS config when using a boolean value
if (typeof config.future.experimental_vcs === 'boolean') {
const vcsConfig = config.future.experimental_vcs
? config.future.faster.gitEagerVcs
? (0, utils_1.getVcsPreset)('default-v2')
: (0, utils_1.getVcsPreset)('default-v1')
: (0, utils_1.getVcsPreset)('disabled');
config.future.experimental_vcs = vcsConfig;
}
if (config.future.faster.ssgWorkerThreads &&
!config.future.v4.removeLegacyPostBuildHeadAttribute) {
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.
If you use Docusaurus Faster, we recommend that you also activate Docusaurus v4 future flags: ${logger_1.default.code('{future: {v4: true}}')}
All the v4 future flags are documented here: https://docusaurus.io/docs/api/docusaurus-config#future`);
}
if (config.future.faster.rspackPersistentCache &&
!config.future.faster.rspackBundler) {
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.`);
}
}
// TODO move to @docusaurus/utils-validation
function validateConfig(config, siteConfigPath) {
const { error, warning, value } = exports.ConfigSchema.validate(config, {
abortEarly: false,
});
(0, utils_validation_1.printWarning)(warning);
if (error) {
const unknownFields = error.details.reduce((formattedError, err) => {
if (err.type === 'object.unknown') {
return `${formattedError}"${err.path.reduce((acc, cur) => typeof cur === 'string' ? `${acc}.${cur}` : `${acc}[${cur}]`)}",`;
}
return formattedError;
}, '');
let formattedError = error.details.reduce((accumulatedErr, err) => err.type !== 'object.unknown'
? `${accumulatedErr}${err.message}\n`
: accumulatedErr, '');
formattedError = unknownFields
? `${formattedError}These field(s) (${unknownFields}) are not recognized in ${siteConfigPath}.\nIf you still want these fields to be in your configuration, put them in the "customFields" field.\nSee https://docusaurus.io/docs/api/docusaurus-config/#customfields`
: formattedError;
throw new Error(formattedError);
}
postProcessDocusaurusConfig(value);
return value;
}