import { rehypeHeadingIds, remarkCollectImages } from "@astrojs/markdown-remark"; import { InvalidAstroDataError, safelyGetAstroData } from "@astrojs/markdown-remark/dist/internal.js"; import { nodeTypes } from "@mdx-js/mdx"; import { visit as estreeVisit } from "estree-util-visit"; import rehypeRaw from "rehype-raw"; import remarkGfm from "remark-gfm"; import remarkSmartypants from "remark-smartypants"; import { rehypeInjectHeadingsExport } from "./rehype-collect-headings.js"; import rehypeMetaString from "./rehype-meta-string.js"; import { rehypeOptimizeStatic } from "./rehype-optimize-static.js"; import { remarkImageToComponent } from "./remark-images-to-component.js"; import remarkPrism from "./remark-prism.js"; import remarkShiki from "./remark-shiki.js"; import { jsToTreeNode } from "./utils.js"; const isPerformanceBenchmark = Boolean(process.env.ASTRO_PERFORMANCE_BENCHMARK); function recmaInjectImportMetaEnvPlugin({ importMetaEnv }) { return (tree) => { estreeVisit(tree, (node) => { if (node.type === "MemberExpression") { const envVarName = getImportMetaEnvVariableName(node); if (typeof envVarName === "string") { for (const key in node) { delete node[key]; } const envVarLiteral = { type: "Literal", value: importMetaEnv[envVarName], raw: JSON.stringify(importMetaEnv[envVarName]) }; Object.assign(node, envVarLiteral); } } }); }; } function rehypeApplyFrontmatterExport() { return function(tree, vfile) { const astroData = safelyGetAstroData(vfile.data); if (astroData instanceof InvalidAstroDataError) throw new Error( // Copied from Astro core `errors-data` // TODO: find way to import error data from core '[MDX] A remark or rehype plugin attempted to inject invalid frontmatter. Ensure "astro.frontmatter" is set to a valid JSON object that is not `null` or `undefined`.' ); const { frontmatter } = astroData; const exportNodes = [ jsToTreeNode(`export const frontmatter = ${JSON.stringify(frontmatter)};`) ]; if (frontmatter.layout) { exportNodes.unshift( jsToTreeNode( /** @see 'vite-plugin-markdown' for layout props reference */ `import { jsx as layoutJsx } from 'astro/jsx-runtime'; export default async function ({ children }) { const Layout = (await import(${JSON.stringify(frontmatter.layout)})).default; const { layout, ...content } = frontmatter; content.file = file; content.url = url; return layoutJsx(Layout, { file, url, content, frontmatter: content, headings: getHeadings(), 'server:root': true, children, }); };` ) ); } tree.children = exportNodes.concat(tree.children); }; } async function getRemarkPlugins(mdxOptions, config) { let remarkPlugins = [ ...config.experimental.assets ? [remarkCollectImages, remarkImageToComponent] : [] ]; if (!isPerformanceBenchmark) { if (mdxOptions.gfm) { remarkPlugins.push(remarkGfm); } if (mdxOptions.smartypants) { remarkPlugins.push(remarkSmartypants); } } remarkPlugins = [...remarkPlugins, ...mdxOptions.remarkPlugins]; if (!isPerformanceBenchmark) { if (mdxOptions.syntaxHighlight === "shiki") { remarkPlugins.push([await remarkShiki(mdxOptions.shikiConfig)]); } if (mdxOptions.syntaxHighlight === "prism") { remarkPlugins.push(remarkPrism); } } return remarkPlugins; } function getRehypePlugins(mdxOptions) { let rehypePlugins = [ // ensure `data.meta` is preserved in `properties.metastring` for rehype syntax highlighters rehypeMetaString, // rehypeRaw allows custom syntax highlighters to work without added config [rehypeRaw, { passThrough: nodeTypes }] ]; rehypePlugins = [ ...rehypePlugins, ...mdxOptions.rehypePlugins, // getHeadings() is guaranteed by TS, so this must be included. // We run `rehypeHeadingIds` _last_ to respect any custom IDs set by user plugins. ...isPerformanceBenchmark ? [] : [rehypeHeadingIds, rehypeInjectHeadingsExport], // computed from `astro.data.frontmatter` in VFile data rehypeApplyFrontmatterExport ]; if (mdxOptions.optimize) { const options = mdxOptions.optimize === true ? void 0 : mdxOptions.optimize; rehypePlugins.push([rehypeOptimizeStatic, options]); } return rehypePlugins; } function getImportMetaEnvVariableName(node) { try { if (node.object.type !== "MemberExpression" || node.property.type !== "Identifier") return new Error(); const nestedExpression = node.object; if (nestedExpression.property.type !== "Identifier" || nestedExpression.property.name !== "env") return new Error(); const envExpression = nestedExpression.object; if (envExpression.type !== "MetaProperty" || envExpression.property.type !== "Identifier" || envExpression.property.name !== "meta") return new Error(); if (envExpression.meta.name !== "import") return new Error(); return node.property.name; } catch (e) { if (e instanceof Error) { return e; } return new Error("Unknown parsing error"); } } export { getRehypePlugins, getRemarkPlugins, recmaInjectImportMetaEnvPlugin, rehypeApplyFrontmatterExport };