Skip to content

Commit

Permalink
Allow remark/rehype plugins added after mdx to work (#10877)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy committed Apr 30, 2024
1 parent d03c9a9 commit 7edbb91
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 8 deletions.
7 changes: 7 additions & 0 deletions .changeset/slimy-cobras-end.md
@@ -0,0 +1,7 @@
---
"@astrojs/mdx": major
---

Allows integrations after the MDX integration to update `markdown.remarkPlugins` and `markdown.rehypePlugins`, and have the plugins work in MDX too.

If you rely on the ordering before to not add remark/rehype plugins for MDX, you need to configure `@astrojs/mdx` with `extendMarkdownConfig: false` and explicitly specify the `remarkPlugins` and `rehypePlugins` options instead.
29 changes: 21 additions & 8 deletions packages/integrations/mdx/src/index.ts
Expand Up @@ -29,6 +29,10 @@ type SetupHookParams = HookParameters<'astro:config:setup'> & {
};

export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroIntegration {
// @ts-expect-error Temporarily assign an empty object here, which will be re-assigned by the
// `astro:config:done` hook later. This is so that `vitePluginMdx` can get hold of a reference earlier.
let mdxOptions: MdxOptions = {};

return {
name: '@astrojs/mdx',
hooks: {
Expand Down Expand Up @@ -58,21 +62,30 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
handlePropagation: true,
});

updateConfig({
vite: {
plugins: [vitePluginMdx(mdxOptions), vitePluginMdxPostprocess(config)],
},
});
},
'astro:config:done': ({ config }) => {
// We resolve the final MDX options here so that other integrations have a chance to modify
// `config.markdown` before we access it
const extendMarkdownConfig =
partialMdxOptions.extendMarkdownConfig ?? defaultMdxOptions.extendMarkdownConfig;

const mdxOptions = applyDefaultOptions({
const resolvedMdxOptions = applyDefaultOptions({
options: partialMdxOptions,
defaults: markdownConfigToMdxOptions(
extendMarkdownConfig ? config.markdown : markdownConfigDefaults
),
});

updateConfig({
vite: {
plugins: [vitePluginMdx(mdxOptions), vitePluginMdxPostprocess(config)],
},
});
// Mutate `mdxOptions` so that `vitePluginMdx` can reference the actual options
Object.assign(mdxOptions, resolvedMdxOptions);
// @ts-expect-error After we assign, we don't need to reference `mdxOptions` in this context anymore.
// Re-assign it so that the garbage can be collected later.
mdxOptions = {};
},
},
};
Expand All @@ -81,7 +94,8 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
const defaultMdxOptions = {
extendMarkdownConfig: true,
recmaPlugins: [],
};
optimize: false,
} satisfies Partial<MdxOptions>;

function markdownConfigToMdxOptions(markdownConfig: typeof markdownConfigDefaults): MdxOptions {
return {
Expand All @@ -90,7 +104,6 @@ function markdownConfigToMdxOptions(markdownConfig: typeof markdownConfigDefault
remarkPlugins: ignoreStringPlugins(markdownConfig.remarkPlugins),
rehypePlugins: ignoreStringPlugins(markdownConfig.rehypePlugins),
remarkRehype: (markdownConfig.remarkRehype as any) ?? {},
optimize: false,
};
}

Expand Down
4 changes: 4 additions & 0 deletions packages/integrations/mdx/src/vite-plugin-mdx.ts
Expand Up @@ -17,6 +17,10 @@ export function vitePluginMdx(mdxOptions: MdxOptions): Plugin {
processor = undefined;
},
configResolved(resolved) {
// `mdxOptions` should be populated at this point, but `astro sync` doesn't call `astro:config:done` :(
// Workaround this for now by skipping here. `astro sync` shouldn't call the `transform()` hook here anyways.
if (Object.keys(mdxOptions).length === 0) return;

processor = createMdxProcessor(mdxOptions, {
sourcemap: !!resolved.build.sourcemap,
});
Expand Down
24 changes: 24 additions & 0 deletions packages/integrations/mdx/test/mdx-plugins.test.js
Expand Up @@ -64,6 +64,30 @@ describe('MDX plugins', () => {
assert.notEqual(selectRehypeExample(document), null);
});

it('supports custom rehype plugins from integrations', async () => {
const fixture = await buildFixture({
integrations: [
mdx(),
{
name: 'test',
hooks: {
'astro:config:setup': ({ updateConfig }) => {
updateConfig({
markdown: {
rehypePlugins: [rehypeExamplePlugin],
}
});
}
}
}
],
});
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);

assert.notEqual(selectRehypeExample(document), null);
});

it('supports custom rehype plugins with namespaced attributes', async () => {
const fixture = await buildFixture({
integrations: [
Expand Down

0 comments on commit 7edbb91

Please sign in to comment.