kjelsrud.dev/node_modules/@astrojs/mdx/dist/index.js

185 lines
7.5 KiB
JavaScript
Raw Normal View History

2023-07-19 21:31:30 +02:00
import { markdownConfigDefaults } from "@astrojs/markdown-remark";
import { toRemarkInitializeAstroData } from "@astrojs/markdown-remark/dist/internal.js";
import { compile as mdxCompile } from "@mdx-js/mdx";
import { parse as parseESM } from "es-module-lexer";
import fs from "node:fs/promises";
import { fileURLToPath } from "node:url";
import { SourceMapGenerator } from "source-map";
import { VFile } from "vfile";
import { getRehypePlugins, getRemarkPlugins, recmaInjectImportMetaEnvPlugin } from "./plugins.js";
import { getFileInfo, ignoreStringPlugins, parseFrontmatter } from "./utils.js";
function mdx(partialMdxOptions = {}) {
return {
name: "@astrojs/mdx",
hooks: {
"astro:config:setup": async (params) => {
const { updateConfig, config, addPageExtension, addContentEntryType, command } = params;
addPageExtension(".mdx");
addContentEntryType({
extensions: [".mdx"],
async getEntryInfo({ fileUrl, contents }) {
const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl));
return {
data: parsed.data,
body: parsed.content,
slug: parsed.data.slug,
rawData: parsed.matter
};
},
contentModuleTypes: await fs.readFile(
new URL("../template/content-module-types.d.ts", import.meta.url),
"utf-8"
),
// MDX can import scripts and styles,
// so wrap all MDX files with script / style propagation checks
handlePropagation: true
});
const extendMarkdownConfig = partialMdxOptions.extendMarkdownConfig ?? defaultMdxOptions.extendMarkdownConfig;
const mdxOptions = applyDefaultOptions({
options: partialMdxOptions,
defaults: markdownConfigToMdxOptions(
extendMarkdownConfig ? config.markdown : markdownConfigDefaults
)
});
const mdxPluginOpts = {
remarkPlugins: await getRemarkPlugins(mdxOptions, config),
rehypePlugins: getRehypePlugins(mdxOptions),
recmaPlugins: mdxOptions.recmaPlugins,
remarkRehypeOptions: mdxOptions.remarkRehype,
jsx: true,
jsxImportSource: "astro",
// Note: disable `.md` (and other alternative extensions for markdown files like `.markdown`) support
format: "mdx",
mdExtensions: []
};
let importMetaEnv = {
SITE: config.site
};
updateConfig({
vite: {
plugins: [
{
name: "@mdx-js/rollup",
enforce: "pre",
configResolved(resolved) {
importMetaEnv = { ...importMetaEnv, ...resolved.env };
},
// Override transform to alter code before MDX compilation
// ex. inject layouts
async transform(_, id) {
var _a;
if (!id.endsWith(".mdx"))
return;
const { fileId } = getFileInfo(id, config);
const code = await fs.readFile(fileId, "utf-8");
const { data: frontmatter, content: pageContent } = parseFrontmatter(code, id);
const compiled = await mdxCompile(new VFile({ value: pageContent, path: id }), {
...mdxPluginOpts,
elementAttributeNameCase: "html",
remarkPlugins: [
// Ensure `data.astro` is available to all remark plugins
toRemarkInitializeAstroData({ userFrontmatter: frontmatter }),
...mdxPluginOpts.remarkPlugins ?? []
],
recmaPlugins: [
...mdxPluginOpts.recmaPlugins ?? [],
() => recmaInjectImportMetaEnvPlugin({ importMetaEnv })
],
SourceMapGenerator: ((_a = config.vite.build) == null ? void 0 : _a.sourcemap) ? SourceMapGenerator : void 0
});
return {
code: escapeViteEnvReferences(String(compiled.value)),
map: compiled.map
};
}
},
{
name: "@astrojs/mdx-postprocess",
// These transforms must happen *after* JSX runtime transformations
transform(code, id) {
if (!id.endsWith(".mdx"))
return;
const [moduleImports, moduleExports] = parseESM(code);
const importsFromJSXRuntime = moduleImports.filter(({ n }) => n === "astro/jsx-runtime").map(({ ss, se }) => code.substring(ss, se));
const hasFragmentImport = importsFromJSXRuntime.some(
(statement) => /[\s,{](Fragment,|Fragment\s*})/.test(statement)
);
if (!hasFragmentImport) {
code = 'import { Fragment } from "astro/jsx-runtime"\n' + code;
}
const { fileUrl, fileId } = getFileInfo(id, config);
if (!moduleExports.find(({ n }) => n === "url")) {
code += `
export const url = ${JSON.stringify(fileUrl)};`;
}
if (!moduleExports.find(({ n }) => n === "file")) {
code += `
export const file = ${JSON.stringify(fileId)};`;
}
if (!moduleExports.find(({ n }) => n === "Content")) {
code = code.replace("export default MDXContent;", "");
code += `
export const Content = (props = {}) => MDXContent({
...props,
components: { Fragment, ...props.components },
});
export default Content;`;
}
code += `
Content[Symbol.for('astro.needsHeadRendering')] = !Boolean(frontmatter.layout);`;
code += `
Content.moduleId = ${JSON.stringify(id)};`;
if (command === "dev") {
code += `
if (import.meta.hot) {
import.meta.hot.decline();
}`;
}
return { code: escapeViteEnvReferences(code), map: null };
}
}
]
}
});
}
}
};
}
const defaultMdxOptions = {
extendMarkdownConfig: true,
recmaPlugins: []
};
function markdownConfigToMdxOptions(markdownConfig) {
return {
...defaultMdxOptions,
...markdownConfig,
remarkPlugins: ignoreStringPlugins(markdownConfig.remarkPlugins),
rehypePlugins: ignoreStringPlugins(markdownConfig.rehypePlugins),
remarkRehype: markdownConfig.remarkRehype ?? {},
optimize: false
};
}
function applyDefaultOptions({
options,
defaults
}) {
return {
syntaxHighlight: options.syntaxHighlight ?? defaults.syntaxHighlight,
extendMarkdownConfig: options.extendMarkdownConfig ?? defaults.extendMarkdownConfig,
recmaPlugins: options.recmaPlugins ?? defaults.recmaPlugins,
remarkRehype: options.remarkRehype ?? defaults.remarkRehype,
gfm: options.gfm ?? defaults.gfm,
smartypants: options.smartypants ?? defaults.smartypants,
remarkPlugins: options.remarkPlugins ?? defaults.remarkPlugins,
rehypePlugins: options.rehypePlugins ?? defaults.rehypePlugins,
shikiConfig: options.shikiConfig ?? defaults.shikiConfig,
optimize: options.optimize ?? defaults.optimize
};
}
function escapeViteEnvReferences(code) {
return code.replace(/import\.meta\.env/g, "import\\u002Emeta.env");
}
export {
mdx as default
};