From 31bd1b188efdbca169063f6d2c3a31a176241d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Wed, 27 Dec 2023 23:19:25 +0100 Subject: [PATCH] feat(mdx-loader): add support for siteConfig.markdown.remarkRehypeOptions (#9674) --- packages/docusaurus-mdx-loader/src/processor.ts | 1 + packages/docusaurus-types/package.json | 1 + packages/docusaurus-types/src/config.d.ts | 10 ++++++++++ .../server/__tests__/__snapshots__/config.test.ts.snap | 10 ++++++++++ .../server/__tests__/__snapshots__/index.test.ts.snap | 1 + .../src/server/__tests__/configValidation.test.ts | 8 ++++++++ packages/docusaurus/src/server/configValidation.ts | 6 ++++++ website/docs/api/docusaurus.config.js.mdx | 2 ++ website/docusaurus.config.localized.json | 4 ++++ website/docusaurus.config.ts | 5 ++++- 10 files changed, 47 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-mdx-loader/src/processor.ts b/packages/docusaurus-mdx-loader/src/processor.ts index 512cd453bfbb..6865f721a999 100644 --- a/packages/docusaurus-mdx-loader/src/processor.ts +++ b/packages/docusaurus-mdx-loader/src/processor.ts @@ -165,6 +165,7 @@ async function createProcessorFactory() { const mdxProcessor = createMdxProcessor({ ...processorOptions, + remarkRehypeOptions: options.markdownConfig.remarkRehypeOptions, format, }); diff --git a/packages/docusaurus-types/package.json b/packages/docusaurus-types/package.json index 9de288df6920..16d40c338856 100644 --- a/packages/docusaurus-types/package.json +++ b/packages/docusaurus-types/package.json @@ -13,6 +13,7 @@ }, "license": "MIT", "dependencies": { + "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", "@types/react": "*", "commander": "^5.1.0", diff --git a/packages/docusaurus-types/src/config.d.ts b/packages/docusaurus-types/src/config.d.ts index 0d872e4001c7..2efea9280b69 100644 --- a/packages/docusaurus-types/src/config.d.ts +++ b/packages/docusaurus-types/src/config.d.ts @@ -10,6 +10,10 @@ import type {Required as RequireKeys, DeepPartial} from 'utility-types'; import type {I18nConfig} from './i18n'; import type {PluginConfig, PresetConfig, HtmlTagObject} from './plugin'; +import type {ProcessorOptions} from '@mdx-js/mdx'; + +export type RemarkRehypeOptions = ProcessorOptions['remarkRehypeOptions']; + export type ReportingSeverity = 'ignore' | 'log' | 'warn' | 'throw'; export type ThemeConfig = { @@ -91,6 +95,12 @@ export type MarkdownConfig = { * See also https://github.com/facebook/docusaurus/issues/4029 */ mdx1Compat: MDX1CompatOptions; + + /** + * Ability to provide custom remark-rehype options + * See also https://github.com/remarkjs/remark-rehype#options + */ + remarkRehypeOptions: RemarkRehypeOptions; }; /** 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 c5d21f81aefc..629e5b02fca2 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap @@ -26,6 +26,7 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", @@ -75,6 +76,7 @@ exports[`loadSiteConfig website with ts + js config 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", @@ -124,6 +126,7 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", @@ -173,6 +176,7 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", @@ -222,6 +226,7 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", @@ -271,6 +276,7 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", @@ -320,6 +326,7 @@ exports[`loadSiteConfig website with valid async config 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", @@ -371,6 +378,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", @@ -422,6 +430,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", @@ -476,6 +485,7 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/index.test.ts.snap index 06caa4c997dc..d3b6b670cc27 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/index.test.ts.snap @@ -100,6 +100,7 @@ exports[`load loads props for site with custom i18n path 1`] = ` "mermaid": false, "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, "onBrokenLinks": "throw", diff --git a/packages/docusaurus/src/server/__tests__/configValidation.test.ts b/packages/docusaurus/src/server/__tests__/configValidation.test.ts index 925207b6366f..ea76af81408b 100644 --- a/packages/docusaurus/src/server/__tests__/configValidation.test.ts +++ b/packages/docusaurus/src/server/__tests__/configValidation.test.ts @@ -69,6 +69,9 @@ describe('normalizeConfig', () => { admonitions: false, headingIds: true, }, + remarkRehypeOptions: { + footnoteLabel: 'Pied de page', + }, }, }; const normalizedConfig = normalizeConfig(userConfig); @@ -514,6 +517,11 @@ describe('markdown', () => { admonitions: true, headingIds: false, }, + remarkRehypeOptions: { + footnoteLabel: 'Notes de bas de page', + // @ts-expect-error: we don't validate it on purpose + anyKey: 'heck we accept it on purpose', + }, }; expect( normalizeConfig({ diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts index 193b8eb6a73d..c020a09cae9f 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -39,6 +39,7 @@ export const DEFAULT_MARKDOWN_CONFIG: MarkdownConfig = { admonitions: true, headingIds: true, }, + remarkRehypeOptions: undefined, }; export const DEFAULT_CONFIG: Pick< @@ -307,6 +308,11 @@ export const ConfigSchema = Joi.object({ DEFAULT_CONFIG.markdown.mdx1Compat.headingIds, ), }).default(DEFAULT_CONFIG.markdown.mdx1Compat), + 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 + Joi.object().unknown(), }).default(DEFAULT_CONFIG.markdown), }).messages({ 'docusaurus.configValidationWarning': diff --git a/website/docs/api/docusaurus.config.js.mdx b/website/docs/api/docusaurus.config.js.mdx index 7e7fbaca779c..47afd62fde98 100644 --- a/website/docs/api/docusaurus.config.js.mdx +++ b/website/docs/api/docusaurus.config.js.mdx @@ -438,6 +438,7 @@ type MarkdownConfig = { preprocessor?: MarkdownPreprocessor; parseFrontMatter?: ParseFrontMatter; mdx1Compat: MDX1CompatOptions; + remarkRehypeOptions: object; // see https://github.com/remarkjs/remark-rehype#options }; ``` @@ -477,6 +478,7 @@ export default { | `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+. | +| `remarkRehypeOptions` | `object` | `undefined` | Makes it possible to pass custom [`remark-rehype` options](https://github.com/remarkjs/remark-rehype#options). | ```mdx-code-block diff --git a/website/docusaurus.config.localized.json b/website/docusaurus.config.localized.json index 1c90178b80c2..4e8553a8d59e 100644 --- a/website/docusaurus.config.localized.json +++ b/website/docusaurus.config.localized.json @@ -2,5 +2,9 @@ "tagline": { "en": "Build optimized websites quickly, focus on your content", "fr": "Construisez rapidement des sites web optimisés, concentrez-vous sur votre contenu" + }, + "remarkRehypeOptions_footnotes": { + "en": "Footnotes", + "fr": "Notes de bas de page" } } diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 06ed9e7031ad..d9d91ae715c7 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -102,7 +102,7 @@ const TwitterSvg = const defaultLocale = 'en'; -function getLocalizedConfigValue(key: string) { +function getLocalizedConfigValue(key: keyof typeof ConfigLocalized) { const currentLocale = process.env.DOCUSAURUS_CURRENT_LOCALE ?? defaultLocale; const values = ConfigLocalized[key]; if (!values) { @@ -177,6 +177,9 @@ export default async function createConfigAsync() { mdx1Compat: { // comments: false, }, + remarkRehypeOptions: { + footnoteLabel: getLocalizedConfigValue('remarkRehypeOptions_footnotes'), + }, parseFrontMatter: async (params) => { const result = await params.defaultParseFrontMatter(params); return {