@astrojs/mdx
Version:
Add support for MDX pages in your Astro site
125 lines (124 loc) • 4.19 kB
JavaScript
import { VFile } from "vfile";
import { isSatteriProcessor, isUnifiedProcessor } from "./processor-guards.js";
import { safeParseFrontmatter } from "./utils.js";
function vitePluginMdx(opts) {
let mdxRenderer;
let sourcemapEnabled;
return {
name: "@mdx-js/rolldown",
enforce: "pre",
buildEnd() {
mdxRenderer = void 0;
},
configResolved(resolved) {
sourcemapEnabled = !!resolved.build.sourcemap;
const jsxPluginIndex = resolved.plugins.findIndex((p) => p.name === "astro:jsx");
if (jsxPluginIndex !== -1) {
resolved.plugins.splice(jsxPluginIndex, 1);
}
},
resolveId: {
filter: {
// Do not match sources that start with /
id: /^[^/]/
},
async handler(source, importer, options) {
if (importer?.endsWith(".mdx")) {
let resolved = await this.resolve(source, importer, options);
if (!resolved) resolved = await this.resolve("./" + source, importer, options);
return resolved;
}
}
},
transform: {
filter: {
id: /\.mdx$/
},
async handler(code, id) {
const { frontmatter, content } = safeParseFrontmatter(code, id);
try {
if (!mdxRenderer) {
mdxRenderer = await resolveMdxRenderer(opts, sourcemapEnabled);
}
const result = await mdxRenderer.process(content, id, frontmatter);
return {
code: result.code,
map: result.map ?? null,
meta: {
astro: result.astroMetadata,
// `lang: 'ts'` makes Vite resolve `.js` import specifiers to `.ts` files.
vite: { lang: "ts" }
}
};
} catch (e) {
const err = e;
err.name = "MDXError";
err.loc = { file: id, line: e.line, column: e.column };
Error.captureStackTrace(err);
throw err;
}
}
}
};
}
async function resolveMdxRenderer(opts, sourcemap) {
const { processor } = opts;
if (processor.createMdxRenderer) {
return processor.createMdxRenderer(
{
syntaxHighlight: opts.mdxOptions.syntaxHighlight,
shikiConfig: opts.mdxOptions.shikiConfig,
gfm: opts.mdxOptions.gfm,
smartypants: opts.mdxOptions.smartypants
},
{ optimize: opts.mdxOptions.optimize, recmaPlugins: opts.mdxOptions.recmaPlugins }
);
}
if (isSatteriProcessor(processor)) {
const { createMdxProcessor: createSatteriMdxProcessor } = await import("./satteri/index.js");
const satteriProcessor = createSatteriMdxProcessor(opts.mdxOptions, processor.options, {
srcDir: opts.srcDir
});
return {
async process(content, filePath, frontmatter) {
const result = await satteriProcessor.process(content, filePath, frontmatter);
return { code: result.code, map: null, astroMetadata: result.astroMetadata };
}
};
}
if (isUnifiedProcessor(processor)) {
const { createMdxProcessor } = await import("./plugins.js");
const { getAstroMetadata } = await import("./rehype-analyze-astro-metadata.js");
const unifiedProcessor = createMdxProcessor(opts.mdxOptions, { sourcemap });
return {
async process(content, filePath, frontmatter) {
const vfile = new VFile({
value: content,
path: filePath,
data: {
astro: { frontmatter },
applyFrontmatterExport: { srcDir: opts.srcDir }
}
});
const compiled = await unifiedProcessor.process(vfile);
const astroMetadata = getAstroMetadata(vfile);
if (!astroMetadata) {
throw new Error(
"Internal MDX error: Astro metadata is not set by rehype-analyze-astro-metadata"
);
}
return {
code: String(compiled.value),
map: compiled.map ? JSON.stringify(compiled.map) : null,
astroMetadata
};
}
};
}
throw new Error(
`The markdown processor "${processor.name}" does not provide MDX support. Implement \`createMdxRenderer\` on the processor to enable MDX rendering.`
);
}
export {
vitePluginMdx
};