From 308e565ad39957e3353d72ca5d3bbce1a1b45008 Mon Sep 17 00:00:00 2001 From: Ben Holmes Date: Mon, 24 Oct 2022 14:27:37 -0400 Subject: [PATCH] [MDX] Support `recmaPlugins` config (#5146) * feat: support recma plugins * chore: add `test:match` to MDX * chore: changeset * docs: add recmaPlugins to README --- .changeset/clever-keys-hammer.md | 5 +++ packages/integrations/mdx/README.md | 6 +++ packages/integrations/mdx/package.json | 3 +- packages/integrations/mdx/src/index.ts | 7 +++- .../mdx-plugins/src/pages/with-plugins.mdx | 4 ++ .../integrations/mdx/test/mdx-plugins.test.js | 38 +++++++++++++++++++ 6 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 .changeset/clever-keys-hammer.md 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 eb769535a4dd..f9bf44ac0d9b 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 @@ -100,7 +102,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]'); +}