[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 <sarah@rainsberger.ca>

* [MDX] Fix remarkRehype docs

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
This commit is contained in:
Thomas Jaggi 2022-11-22 16:12:25 +01:00 committed by GitHub
parent fcada72bd5
commit 2a1c085b19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 126 additions and 7 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/mdx': minor
---
Uses remark-rehype options from astro.config.mjs

View file

@ -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.

View file

@ -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"

View file

@ -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<string, any> = {

View file

@ -0,0 +1,5 @@
# Hello world
This[^1] should be visible.
[^1]: And there would be a footnote.

View file

@ -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'
);
});
});

View file

@ -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==}