124 lines
4.1 KiB
JavaScript
124 lines
4.1 KiB
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
|
|
};
|