diff --git a/.changeset/clever-keys-hammer.md b/.changeset/clever-keys-hammer.md new file mode 100644 index 000000000000..5e91f47e470b --- /dev/null +++ b/.changeset/clever-keys-hammer.md @@ -0,0 +1,5 @@ +--- +'@astrojs/mdx': patch +--- + +Support recmaPlugins config option diff --git a/packages/integrations/mdx/README.md b/packages/integrations/mdx/README.md index 0f287b44b1c9..efb5f3b1967e 100644 --- a/packages/integrations/mdx/README.md +++ b/packages/integrations/mdx/README.md @@ -509,6 +509,12 @@ export default { } ``` +### recmaPlugins + +These are plugins that modify the output [estree](https://github.com/estree/estree) directly. This is useful for modifying or injecting JavaScript variables in your MDX files. + +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. + ## 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 2a16ad801d66..6ef66c27e55f 100644 --- a/packages/integrations/mdx/package.json +++ b/packages/integrations/mdx/package.json @@ -26,7 +26,8 @@ "build": "astro-scripts build \"src/**/*.ts\" && tsc", "build:ci": "astro-scripts build \"src/**/*.ts\"", "dev": "astro-scripts dev \"src/**/*.ts\"", - "test": "mocha --exit --timeout 20000" + "test": "mocha --exit --timeout 20000", + "test:match": "mocha --timeout 20000 -g" }, "dependencies": { "@astrojs/prism": "^1.0.1", diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts index 7c535646b49b..622ac7a216d2 100644 --- a/packages/integrations/mdx/src/index.ts +++ b/packages/integrations/mdx/src/index.ts @@ -24,6 +24,7 @@ const COMPILED_CONTENT_ERROR = export type MdxOptions = { remarkPlugins?: PluggableList; rehypePlugins?: PluggableList; + recmaPlugins?: PluggableList; /** * Choose which remark and rehype plugins to inherit, if any. * @@ -64,6 +65,7 @@ export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration { const mdxPluginOpts: MdxRollupPluginOptions = { remarkPlugins: await getRemarkPlugins(mdxOptions, config), rehypePlugins: getRehypePlugins(mdxOptions, config), + recmaPlugins: mdxOptions.recmaPlugins, jsx: true, jsxImportSource: 'astro', // Note: disable `.md` support @@ -101,7 +103,10 @@ export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration { ...(mdxPluginOpts.rehypePlugins ?? []), () => rehypeApplyFrontmatterExport(frontmatter), ], - recmaPlugins: [() => recmaInjectImportMetaEnvPlugin({ importMetaEnv })], + recmaPlugins: [ + ...(mdxPluginOpts.recmaPlugins ?? []), + () => recmaInjectImportMetaEnvPlugin({ importMetaEnv }), + ], }); return { diff --git a/packages/integrations/mdx/test/fixtures/mdx-plugins/src/pages/with-plugins.mdx b/packages/integrations/mdx/test/fixtures/mdx-plugins/src/pages/with-plugins.mdx index fe9cac3ee266..fcd8ae181827 100644 --- a/packages/integrations/mdx/test/fixtures/mdx-plugins/src/pages/with-plugins.mdx +++ b/packages/integrations/mdx/test/fixtures/mdx-plugins/src/pages/with-plugins.mdx @@ -1,3 +1,5 @@ +export let recmaPluginWorking = false + # TOC test ## Table of contents @@ -17,3 +19,5 @@ Oh cool, more text! ## Section 2 And section 2, with a hyperlink to check GFM is preserved: https://handle-me-gfm.com + +
diff --git a/packages/integrations/mdx/test/mdx-plugins.test.js b/packages/integrations/mdx/test/mdx-plugins.test.js index 4cbfaae3ef75..a077fde450f8 100644 --- a/packages/integrations/mdx/test/mdx-plugins.test.js +++ b/packages/integrations/mdx/test/mdx-plugins.test.js @@ -4,6 +4,7 @@ import { expect } from 'chai'; import { parseHTML } from 'linkedom'; import { loadFixture } from '../../../astro/test/test-utils.js'; import remarkToc from 'remark-toc'; +import { visit as estreeVisit } from 'estree-util-visit'; const FIXTURE_ROOT = new URL('./fixtures/mdx-plugins/', import.meta.url); const FILE = '/with-plugins/index.html'; @@ -164,6 +165,21 @@ describe('MDX plugins', () => { expect(selectGfmLink(document)).to.be.null; expect(selectRemarkExample(document)).to.be.null; }); + + it('supports custom recma plugins', async () => { + const fixture = await buildFixture({ + integrations: [ + mdx({ + recmaPlugins: [recmaExamplePlugin], + }), + ], + }); + + const html = await fixture.readFile(FILE); + const { document } = parseHTML(html); + + expect(selectRecmaExample(document)).to.not.be.null; + }); }); async function buildFixture(config) { @@ -194,6 +210,24 @@ function rehypeExamplePlugin() { }; } +function recmaExamplePlugin() { + return (tree) => { + estreeVisit(tree, (node) => { + if ( + node.type === 'VariableDeclarator' && + node.id.name === 'recmaPluginWorking' && + node.init?.type === 'Literal' + ) { + node.init = { + ...(node.init ?? {}), + value: true, + raw: 'true', + }; + } + }); + }; +} + function selectTocLink(document) { return document.querySelector('ul a[href="#section-1"]'); } @@ -209,3 +243,7 @@ function selectRemarkExample(document) { function selectRehypeExample(document) { return document.querySelector('div[data-rehype-plugin-works]'); } + +function selectRecmaExample(document) { + return document.querySelector('div[data-recma-plugin-works]'); +}