diff --git a/packages/docusaurus-types/src/config.d.ts b/packages/docusaurus-types/src/config.d.ts index b6d3d8a0a396..6f88b68dc6c6 100644 --- a/packages/docusaurus-types/src/config.d.ts +++ b/packages/docusaurus-types/src/config.d.ts @@ -41,6 +41,7 @@ export type FutureV4Config = { useCssCascadeLayers: boolean; siteStorageNamespacing: boolean; fasterByDefault: boolean; + mdx1CompatDisabledByDefault: boolean; }; // VCS (Version Control System) info about a given change, e.g., a git commit. diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index 6d153c387a71..6dfca63d1f70 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -21,6 +21,7 @@ export { } from './config'; export { + MDX1CompatOptions, MarkdownConfig, MarkdownHooks, DefaultParseFrontMatter, diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap index c0437a9e133a..35701f702613 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap @@ -27,6 +27,7 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -114,6 +115,7 @@ exports[`loadSiteConfig website with ts + js config 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -201,6 +203,7 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -288,6 +291,7 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -375,6 +379,7 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -462,6 +467,7 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -549,6 +555,7 @@ exports[`loadSiteConfig website with valid async config 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -638,6 +645,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -727,6 +735,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -819,6 +828,7 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap index a6999ad02ad6..d10c593e052c 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap @@ -107,6 +107,7 @@ exports[`loadSite custom-i18n-site loads site 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -282,6 +283,7 @@ exports[`loadSite simple-site-with-baseUrl loads site - custom config 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -449,6 +451,7 @@ exports[`loadSite simple-site-with-baseUrl loads site - custom outDir 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -616,6 +619,7 @@ exports[`loadSite simple-site-with-baseUrl loads site 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -827,6 +831,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale fr + custom }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -1060,6 +1065,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - custom outDir 1`] = }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -1293,6 +1299,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale de 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -1526,6 +1533,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale en 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -1759,6 +1767,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale es 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -1992,6 +2001,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale fr 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -2225,6 +2235,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale it 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, @@ -2458,6 +2469,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site 1`] = ` }, "v4": { "fasterByDefault": false, + "mdx1CompatDisabledByDefault": false, "removeLegacyPostBuildHeadAttribute": false, "siteStorageNamespacing": false, "useCssCascadeLayers": false, diff --git a/packages/docusaurus/src/server/__tests__/configValidation.test.ts b/packages/docusaurus/src/server/__tests__/configValidation.test.ts index 63c58e82da1e..6ed937c2a31d 100644 --- a/packages/docusaurus/src/server/__tests__/configValidation.test.ts +++ b/packages/docusaurus/src/server/__tests__/configValidation.test.ts @@ -67,6 +67,7 @@ describe('normalizeConfig', () => { useCssCascadeLayers: true, siteStorageNamespacing: true, fasterByDefault: true, + mdx1CompatDisabledByDefault: true, }, faster: { swcJsLoader: true, @@ -513,6 +514,7 @@ describe('markdown', () => { ): MarkdownConfig { return normalizeConfig({markdown}).markdown; } + it('accepts undefined object', () => { expect(normalizeMarkdown(undefined)).toEqual(DEFAULT_CONFIG.markdown); }); @@ -1348,6 +1350,7 @@ describe('future', () => { useCssCascadeLayers: true, siteStorageNamespacing: true, fasterByDefault: true, + mdx1CompatDisabledByDefault: true, }, faster: { swcJsLoader: true, @@ -2566,6 +2569,7 @@ describe('future', () => { useCssCascadeLayers: true, siteStorageNamespacing: true, fasterByDefault: true, + mdx1CompatDisabledByDefault: true, }; expect( normalizeConfig({ @@ -2906,5 +2910,64 @@ describe('future', () => { `); }); }); + + describe('mdx1CompatDisabledByDefault', () => { + function mdx1CompatContaining(mdx1Compat: object) { + return expect.objectContaining({ + markdown: expect.objectContaining({mdx1Compat}), + }); + } + + const MDX1_COMPAT_ALL_TRUE = { + comments: true, + admonitions: true, + headingIds: true, + }; + + const MDX1_COMPAT_ALL_FALSE = { + comments: false, + admonitions: false, + headingIds: false, + }; + + it('defaults mdx1Compat to all true when flag is off', () => { + expect(normalizeConfig({})).toEqual( + mdx1CompatContaining(MDX1_COMPAT_ALL_TRUE), + ); + }); + + it('defaults mdx1Compat to all false when flag is on', () => { + expect( + normalizeConfig({ + future: {v4: {mdx1CompatDisabledByDefault: true}}, + }), + ).toEqual(mdx1CompatContaining(MDX1_COMPAT_ALL_FALSE)); + }); + + it('defaults mdx1Compat to all false when v4: true', () => { + expect( + normalizeConfig({ + future: {v4: true}, + }), + ).toEqual(mdx1CompatContaining(MDX1_COMPAT_ALL_FALSE)); + }); + + it('keeps explicit mdx1Compat overrides when flag is on', () => { + expect( + normalizeConfig({ + future: {v4: {mdx1CompatDisabledByDefault: true}}, + markdown: { + mdx1Compat: {admonitions: true}, + }, + }), + ).toEqual( + mdx1CompatContaining({ + comments: false, + admonitions: true, + headingIds: false, + }), + ); + }); + }); }); }); diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts index 5558b509ca75..724f4ea70cf2 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -26,6 +26,7 @@ import type { FutureV4Config, I18nConfig, I18nLocaleConfig, + MDX1CompatOptions, MarkdownConfig, MarkdownHooks, StorageConfig, @@ -102,6 +103,7 @@ export const DEFAULT_FUTURE_V4_CONFIG: FutureV4Config = { useCssCascadeLayers: false, siteStorageNamespacing: false, fasterByDefault: false, + mdx1CompatDisabledByDefault: false, }; // When using the "v4: true" shortcut @@ -110,6 +112,7 @@ export const DEFAULT_FUTURE_V4_CONFIG_TRUE: FutureV4Config = { useCssCascadeLayers: true, siteStorageNamespacing: true, fasterByDefault: true, + mdx1CompatDisabledByDefault: true, }; export const DEFAULT_FUTURE_CONFIG: FutureConfig = { @@ -124,17 +127,22 @@ export const DEFAULT_MARKDOWN_HOOKS: MarkdownHooks = { onBrokenMarkdownImages: 'throw', }; +export const DEFAULT_MARKDOWN_MDX1COMPAT: MDX1CompatOptions = { + comments: true, + admonitions: true, + headingIds: true, +}; + export const DEFAULT_MARKDOWN_CONFIG: MarkdownConfig = { - format: 'mdx', // TODO change this to "detect" in Docusaurus v4? + // 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: DEFAULT_PARSE_FRONT_MATTER, - mdx1Compat: { - comments: true, - admonitions: true, - headingIds: true, - }, + mdx1Compat: DEFAULT_MARKDOWN_MDX1COMPAT, anchors: { maintainCase: false, }, @@ -319,6 +327,9 @@ const FUTURE_V4_SCHEMA = Joi.alternatives() fasterByDefault: Joi.boolean().default( DEFAULT_FUTURE_V4_CONFIG.fasterByDefault, ), + mdx1CompatDisabledByDefault: Joi.boolean().default( + DEFAULT_FUTURE_V4_CONFIG.mdx1CompatDisabledByDefault, + ), }), Joi.boolean() .required() @@ -511,17 +522,14 @@ export const ConfigSchema = Joi.object({ .arity(1) .optional() .default(() => 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: Joi.object({ - comments: Joi.boolean().default( - DEFAULT_CONFIG.markdown.mdx1Compat.comments, - ), - admonitions: Joi.boolean().default( - DEFAULT_CONFIG.markdown.mdx1Compat.admonitions, - ), - headingIds: Joi.boolean().default( - DEFAULT_CONFIG.markdown.mdx1Compat.headingIds, - ), - }).default(DEFAULT_CONFIG.markdown.mdx1Compat), + comments: Joi.boolean(), + admonitions: Joi.boolean(), + headingIds: Joi.boolean(), + }).default({}), remarkRehypeOptions: // add proper external options validation? // Not sure if it's a good idea, validation is likely to become stale @@ -546,7 +554,12 @@ export const ConfigSchema = Joi.object({ ) .default(DEFAULT_CONFIG.markdown.hooks.onBrokenMarkdownImages), }).default(DEFAULT_CONFIG.markdown.hooks), - }).default(DEFAULT_CONFIG.markdown), + }).default({ + ...DEFAULT_CONFIG.markdown, + mdx1Compat: { + // erased on purpose, filled using postprocessing + }, + }), }).messages({ 'docusaurus.configValidationWarning': 'Docusaurus config validation warning. Field {#label}: {#warningMessage}', @@ -576,6 +589,16 @@ function postProcessDocusaurusConfig(config: DocusaurusConfig) { } } + // 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( + DEFAULT_MARKDOWN_MDX1COMPAT, + ) as (keyof MDX1CompatOptions)[]; + for (const key of mdx1CompatKeys) { + config.markdown.mdx1Compat[key] ??= mdx1CompatDefault; + } + if (config.onBrokenMarkdownLinks) { logger.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.`; diff --git a/website/docs/api/docusaurus.config.js.mdx b/website/docs/api/docusaurus.config.js.mdx index 8e0019f461aa..f1547f79aef0 100644 --- a/website/docs/api/docusaurus.config.js.mdx +++ b/website/docs/api/docusaurus.config.js.mdx @@ -254,6 +254,7 @@ export default { useCssCascadeLayers: true, siteStorageNamespacing: true, fasterByDefault: true, + mdx1CompatDisabledByDefault: true, }, faster: { swcJsLoader: true, @@ -275,6 +276,7 @@ export default { - [`useCssCascadeLayers`](https://github.com/facebook/docusaurus/pull/11142): This enables the [Docusaurus CSS Cascade Layers plugin](./plugins/plugin-css-cascade-layers.mdx) with pre-configured layers that we plan to apply by default for Docusaurus v4. - `siteStorageNamespacing`: Defaults the [`storage.namespace`](#storage) config to `true` instead of `false`. This enables automatic browser storage key namespacing, which avoids storage key conflicts when multiple Docusaurus sites are hosted under the same domain, or on localhost. - `fasterByDefault`: Defaults all `future.faster` flags to `true` instead of `false`. This enables [Docusaurus Faster](https://github.com/facebook/docusaurus/issues/10556) features by default. Requires having `@docusaurus/faster` in your dependencies. If you explicitly set individual `faster` flags, those explicit values take precedence. + - `mdx1CompatDisabledByDefault`: Defaults all [`markdown.mdx1Compat`](#markdown) flags to `false` instead of `true`. This prepares your site for Docusaurus v4, which will not enable MDX v1 compatibility by default. If you explicitly set individual `mdx1Compat` flags, those explicit values take precedence. - `faster`: An object containing feature flags to make the Docusaurus build faster. This requires adding the `@docusaurus/faster` package to your site's dependencies. Use `true` as a shorthand to enable all flags. Read more on the [Docusaurus Faster](https://github.com/facebook/docusaurus/issues/10556) issue. Available feature flags: - [`swcJsLoader`](https://github.com/facebook/docusaurus/pull/10435): Use [SWC](https://swc.rs/) to transpile JS (instead of [Babel](https://babeljs.io/)). - [`swcJsMinimizer`](https://github.com/facebook/docusaurus/pull/10441): Use [SWC](https://swc.rs/) to minify JS (instead of [Terser](https://github.com/terser/terser)). @@ -734,7 +736,7 @@ export default { | `emoji` | `boolean` | `true` | When `true`, allows Docusaurus to render emoji shortcodes (e.g., `:+1:`) as Unicode emoji (👍). When `false`, emoji shortcodes are left as-is. | | `preprocessor` | `MarkdownPreprocessor` | `undefined` | Gives you the ability to alter the Markdown content string before parsing. Use it as a last-resort escape hatch or workaround: it is almost always better to implement a Remark/Rehype plugin. | | `parseFrontMatter` | `ParseFrontMatter` | `undefined` | Gives you the ability to provide your own front matter parser, or to enhance the default parser. Read our [front matter guide](../guides/markdown-features/markdown-features-intro.mdx#front-matter) for details. | -| `mdx1Compat` | `MDX1CompatOptions` | `{comments: true, admonitions: true, headingIds: true}` | Compatibility options to make it easier to upgrade to Docusaurus v3+. | +| `mdx1Compat` | `MDX1CompatOptions` | `{comments: true, admonitions: true, headingIds: true}` | Compatibility options to make it easier to upgrade to Docusaurus v3+. Defaults to all `false` when [`future.v4.mdx1CompatDisabledByDefault`](#future) is enabled. | | `anchors` | `MarkdownAnchorsConfig` | `{maintainCase: false}` | Options to control the behavior of anchors generated from Markdown headings | | `remarkRehypeOptions` | `object` | `undefined` | Makes it possible to pass custom [`remark-rehype` options](https://github.com/remarkjs/remark-rehype#options). | | `hooks` | `MarkdownHooks` | `object` | Make it possible to customize the MDX loader behavior with callbacks or built-in options. | diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index e0477b74bc17..7246fcc3266e 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -234,8 +234,9 @@ export default async function createConfigAsync() { onBrokenMarkdownLinks: 'warn', }, mdx1Compat: { - headingIds: false, - comments: false, + // Needed for us until Crowdin improves support + // See https://github.com/facebook/docusaurus/pull/11847#issuecomment-4183213345 + admonitions: true, }, remarkRehypeOptions: { footnoteLabel: getLocalizedConfigValue('remarkRehypeOptions_footnotes'),