From 2a1c085b199f24e34424ec8c19041c03602c53c5 Mon Sep 17 00:00:00 2001 From: Thomas Jaggi Date: Tue, 22 Nov 2022 16:12:25 +0100 Subject: [PATCH] [MDX] Support remark-rehype options from Astro Markdown config (#5427) * [MDX] Support remark-rehype options from Astro Markdown config * [MDX] Add remarkRehype to MdxOptions, extend with default markdown config * [MDX] Add remarkRehype to README * [MDX] Fix remarkRehype inheritance, add tests * [MDX] Update remarkRehype docs in README Co-authored-by: Sarah Rainsberger * [MDX] Fix remarkRehype docs Co-authored-by: Sarah Rainsberger --- .changeset/nice-jokes-smile.md | 5 ++ packages/integrations/mdx/README.md | 20 +++++ packages/integrations/mdx/package.json | 1 + packages/integrations/mdx/src/index.ts | 12 +++ .../src/pages/index.mdx | 5 ++ .../mdx-astro-markdown-remarkRehype.test.js | 81 +++++++++++++++++++ pnpm-lock.yaml | 9 +-- 7 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 .changeset/nice-jokes-smile.md create mode 100644 packages/integrations/mdx/test/fixtures/mdx-astro-markdown-remarkRehype/src/pages/index.mdx create mode 100644 packages/integrations/mdx/test/mdx-astro-markdown-remarkRehype.test.js diff --git a/.changeset/nice-jokes-smile.md b/.changeset/nice-jokes-smile.md new file mode 100644 index 000000000000..ebbb7377c8ec --- /dev/null +++ b/.changeset/nice-jokes-smile.md @@ -0,0 +1,5 @@ +--- +'@astrojs/mdx': minor +--- + +Uses remark-rehype options from astro.config.mjs diff --git a/packages/integrations/mdx/README.md b/packages/integrations/mdx/README.md index b3cc535aee7a..0193da4cb2e3 100644 --- a/packages/integrations/mdx/README.md +++ b/packages/integrations/mdx/README.md @@ -518,6 +518,26 @@ These are plugins that modify the output [estree](https://github.com/estree/estr We suggest [using AST Explorer](https://astexplorer.net/) to play with estree outputs, and trying [`estree-util-visit`](https://unifiedjs.com/explore/package/estree-util-visit/) for searching across JavaScript nodes. +### remarkRehype + +Markdown content is transformed into HTML through remark-rehype which has [a number of options](https://github.com/remarkjs/remark-rehype#options). + +You can use remark-rehype options in your MDX integration config file like so: + +```js +// astro.config.mjs +export default { + integrations: [mdx({ + remarkRehype: { + footnoteLabel: 'Catatan kaki', + footnoteBackLabel: 'Kembali ke konten', + }, + })], +}; +``` + +This inherits the configuration of `markdown.remarkRehype`. This behavior can be changed by configuring `extendPlugins`. + ## Examples - The [Astro MDX example](https://github.com/withastro/astro/tree/latest/examples/with-mdx) shows how to use MDX files in your Astro project. diff --git a/packages/integrations/mdx/package.json b/packages/integrations/mdx/package.json index 41ff139ce095..152f0746612d 100644 --- a/packages/integrations/mdx/package.json +++ b/packages/integrations/mdx/package.json @@ -63,6 +63,7 @@ "mocha": "^9.2.2", "reading-time": "^1.5.0", "rehype-pretty-code": "^0.4.0", + "remark-rehype": "^10.1.0", "remark-shiki-twoslash": "^3.1.0", "remark-toc": "^8.0.1", "vite": "^3.0.0" diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts index 4bac982af6bc..33286b2e2799 100644 --- a/packages/integrations/mdx/src/index.ts +++ b/packages/integrations/mdx/src/index.ts @@ -1,3 +1,4 @@ +import type { Options as RemarkRehypeOptions } from 'remark-rehype'; import { compile as mdxCompile } from '@mdx-js/mdx'; import { PluggableList } from '@mdx-js/mdx/lib/core.js'; import mdxPlugin, { Options as MdxRollupPluginOptions } from '@mdx-js/rollup'; @@ -33,6 +34,7 @@ export type MdxOptions = { * - false - do not inherit any plugins */ extendPlugins?: 'markdown' | 'astroDefaults' | false; + remarkRehype?: RemarkRehypeOptions; }; export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration { @@ -62,6 +64,15 @@ export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration { console.info(`See "extendPlugins" option to configure this behavior.`); } + let remarkRehypeOptions = mdxOptions.remarkRehype; + + if (mdxOptions.extendPlugins === 'markdown') { + remarkRehypeOptions = { + ...config.markdown.remarkRehype, + ...remarkRehypeOptions, + }; + } + const mdxPluginOpts: MdxRollupPluginOptions = { remarkPlugins: await getRemarkPlugins(mdxOptions, config), rehypePlugins: getRehypePlugins(mdxOptions, config), @@ -71,6 +82,7 @@ export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration { // Note: disable `.md` (and other alternative extensions for markdown files like `.markdown`) support format: 'mdx', mdExtensions: [], + remarkRehypeOptions, }; let importMetaEnv: Record = { diff --git a/packages/integrations/mdx/test/fixtures/mdx-astro-markdown-remarkRehype/src/pages/index.mdx b/packages/integrations/mdx/test/fixtures/mdx-astro-markdown-remarkRehype/src/pages/index.mdx new file mode 100644 index 000000000000..8b8f1d189be9 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/mdx-astro-markdown-remarkRehype/src/pages/index.mdx @@ -0,0 +1,5 @@ +# Hello world + +This[^1] should be visible. + +[^1]: And there would be a footnote. \ No newline at end of file diff --git a/packages/integrations/mdx/test/mdx-astro-markdown-remarkRehype.test.js b/packages/integrations/mdx/test/mdx-astro-markdown-remarkRehype.test.js new file mode 100644 index 000000000000..778849207d6d --- /dev/null +++ b/packages/integrations/mdx/test/mdx-astro-markdown-remarkRehype.test.js @@ -0,0 +1,81 @@ +import mdx from '@astrojs/mdx'; + +import { expect } from 'chai'; +import { parseHTML } from 'linkedom'; +import { loadFixture } from '../../../astro/test/test-utils.js'; + +describe('MDX with Astro Markdown remark-rehype config', () => { + it('Renders footnotes with values from the default configuration', async () => { + const fixture = await loadFixture({ + root: new URL('./fixtures/mdx-astro-markdown-remarkRehype/', import.meta.url), + integrations: [mdx()], + markdown: { + remarkRehype: { + footnoteLabel: 'Catatan kaki', + footnoteBackLabel: 'Kembali ke konten', + }, + }, + }); + + await fixture.build(); + const html = await fixture.readFile('/index.html'); + const { document } = parseHTML(html); + + expect(document.querySelector('#footnote-label').textContent).to.equal('Catatan kaki'); + expect(document.querySelector('.data-footnote-backref').getAttribute('aria-label')).to.equal( + 'Kembali ke konten' + ); + }); + + it('Renders footnotes with values from custom configuration extending the default', async () => { + const fixture = await loadFixture({ + root: new URL('./fixtures/mdx-astro-markdown-remarkRehype/', import.meta.url), + integrations: [mdx({ + remarkRehype: { + footnoteLabel: 'Catatan kaki', + footnoteBackLabel: 'Kembali ke konten', + }, + })], + markdown: { + remarkRehype: { + footnoteBackLabel: 'Replace me', + }, + }, + }); + + await fixture.build(); + const html = await fixture.readFile('/index.html'); + const { document } = parseHTML(html); + + expect(document.querySelector('#footnote-label').textContent).to.equal('Catatan kaki'); + expect(document.querySelector('.data-footnote-backref').getAttribute('aria-label')).to.equal( + 'Kembali ke konten' + ); + }); + + it('Renders footnotes with values from custom configuration without extending the default', async () => { + const fixture = await loadFixture({ + root: new URL('./fixtures/mdx-astro-markdown-remarkRehype/', import.meta.url), + integrations: [mdx({ + extendPlugins: 'astroDefaults', + remarkRehype: { + footnoteLabel: 'Catatan kaki', + }, + })], + markdown: { + remarkRehype: { + footnoteBackLabel: 'Kembali ke konten', + }, + }, + }); + + await fixture.build(); + const html = await fixture.readFile('/index.html'); + const { document } = parseHTML(html); + + expect(document.querySelector('#footnote-label').textContent).to.equal('Catatan kaki'); + expect(document.querySelector('.data-footnote-backref').getAttribute('aria-label')).to.equal( + 'Back to content' + ); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c6fcfa56c5cd..bbb484832a38 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2817,6 +2817,7 @@ importers: rehype-raw: ^6.1.1 remark-frontmatter: ^4.0.1 remark-gfm: ^3.0.1 + remark-rehype: ^10.1.0 remark-shiki-twoslash: ^3.1.0 remark-smartypants: ^2.0.0 remark-toc: ^8.0.1 @@ -2857,6 +2858,7 @@ importers: mocha: 9.2.2 reading-time: 1.5.0 rehype-pretty-code: 0.4.0_shiki@0.11.1 + remark-rehype: 10.1.0 remark-shiki-twoslash: 3.1.0 remark-toc: 8.0.1 vite: 3.2.3 @@ -14173,7 +14175,6 @@ packages: '@types/mdast': 3.0.10 '@types/unist': 2.0.6 unist-util-visit: 4.1.1 - dev: false /mdast-util-find-and-replace/2.2.1: resolution: {integrity: sha512-SobxkQXFAdd4b5WmEakmkVoh18icjQRxGy5OWTCzgsLRm1Fu/KCtwD1HIQSsmq5ZRjVH0Ehwg6/Fn3xIUk+nKw==} @@ -14333,7 +14334,6 @@ packages: unist-util-generated: 2.0.0 unist-util-position: 4.0.3 unist-util-visit: 4.1.1 - dev: false /mdast-util-to-markdown/1.3.0: resolution: {integrity: sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA==} @@ -16384,7 +16384,6 @@ packages: '@types/mdast': 3.0.10 mdast-util-to-hast: 12.2.4 unified: 10.1.2 - dev: false /remark-shiki-twoslash/3.1.0: resolution: {integrity: sha512-6LqSqVtHQR4S0DKfdQ2/ePn9loTKUtpyopYvwk8johjDTeUW5MkaLQuZHlWNkkST/4aMbz6aTkstIcwfwcHpXg==} @@ -17449,7 +17448,6 @@ packages: /trim-lines/3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - dev: false /trim-newlines/3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} @@ -17805,11 +17803,9 @@ packages: resolution: {integrity: sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==} dependencies: '@types/unist': 2.0.6 - dev: false /unist-util-generated/2.0.0: resolution: {integrity: sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==} - dev: false /unist-util-is/3.0.0: resolution: {integrity: sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==} @@ -17844,7 +17840,6 @@ packages: resolution: {integrity: sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==} dependencies: '@types/unist': 2.0.6 - dev: false /unist-util-remove-position/4.0.1: resolution: {integrity: sha512-0yDkppiIhDlPrfHELgB+NLQD5mfjup3a8UYclHruTJWmY74je8g+CIFr79x5f6AkmzSwlvKLbs63hC0meOMowQ==}