summaryrefslogtreecommitdiff
path: root/packages/integrations/mdx/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/integrations/mdx/src')
-rw-r--r--packages/integrations/mdx/src/index.ts66
-rw-r--r--packages/integrations/mdx/src/plugins.ts62
-rw-r--r--packages/integrations/mdx/src/utils.ts24
3 files changed, 101 insertions, 51 deletions
diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts
index 901ffb6bd..3e9cc945c 100644
--- a/packages/integrations/mdx/src/index.ts
+++ b/packages/integrations/mdx/src/index.ts
@@ -3,14 +3,15 @@ import { toRemarkInitializeAstroData } from '@astrojs/markdown-remark/dist/inter
import { compile as mdxCompile } from '@mdx-js/mdx';
import { PluggableList } from '@mdx-js/mdx/lib/core.js';
import mdxPlugin, { Options as MdxRollupPluginOptions } from '@mdx-js/rollup';
-import type { AstroIntegration } from 'astro';
+import type { AstroIntegration, ContentEntryType, HookParameters } from 'astro';
import { parse as parseESM } from 'es-module-lexer';
import fs from 'node:fs/promises';
+import { fileURLToPath } from 'node:url';
import type { Options as RemarkRehypeOptions } from 'remark-rehype';
import { VFile } from 'vfile';
import type { Plugin as VitePlugin } from 'vite';
import { getRehypePlugins, getRemarkPlugins, recmaInjectImportMetaEnvPlugin } from './plugins.js';
-import { getFileInfo, parseFrontmatter } from './utils.js';
+import { getFileInfo, parseFrontmatter, ignoreStringPlugins } from './utils.js';
export type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlugins' | 'rehypePlugins'> & {
extendMarkdownConfig: boolean;
@@ -22,19 +23,54 @@ export type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlugins' | '
remarkRehype: RemarkRehypeOptions;
};
-export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroIntegration {
+
+type IntegrationWithPrivateHooks = {
+ name: string;
+ hooks: Omit<AstroIntegration['hooks'], 'astro:config:setup'> & {
+ 'astro:config:setup': (params: HookParameters<'astro:config:setup'> & {
+ // `addPageExtension` and `contentEntryType` are not a public APIs
+ // Add type defs here
+ addPageExtension: (extension: string) => void
+ addContentEntryType: (contentEntryType: ContentEntryType) => void
+ }) => void | Promise<void>;
+ };
+};
+
+export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): IntegrationWithPrivateHooks {
return {
name: '@astrojs/mdx',
hooks: {
- 'astro:config:setup': async ({ updateConfig, config, addPageExtension, command }: any) => {
+ 'astro:config:setup': async ({
+ updateConfig,
+ config,
+ addPageExtension,
+ addContentEntryType,
+ command,
+ }) => {
addPageExtension('.mdx');
+ addContentEntryType({
+ extensions: ['.mdx'],
+ async getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string }) {
+ 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'
+ ),
+ });
const extendMarkdownConfig =
- partialMdxOptions.extendMarkdownConfig ?? defaultOptions.extendMarkdownConfig;
+ partialMdxOptions.extendMarkdownConfig ?? defaultMdxOptions.extendMarkdownConfig;
const mdxOptions = applyDefaultOptions({
options: partialMdxOptions,
- defaults: extendMarkdownConfig ? config.markdown : defaultOptions,
+ defaults: markdownConfigToMdxOptions(extendMarkdownConfig ? config.markdown : markdownConfigDefaults),
});
const mdxPluginOpts: MdxRollupPluginOptions = {
@@ -149,14 +185,20 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
};
}
-const defaultOptions: MdxOptions = {
- ...markdownConfigDefaults,
+const defaultMdxOptions = {
extendMarkdownConfig: true,
recmaPlugins: [],
- remarkPlugins: [],
- rehypePlugins: [],
- remarkRehype: {},
-};
+}
+
+function markdownConfigToMdxOptions(markdownConfig: typeof markdownConfigDefaults): MdxOptions {
+ return {
+ ...defaultMdxOptions,
+ ...markdownConfig,
+ remarkPlugins: ignoreStringPlugins(markdownConfig.remarkPlugins),
+ rehypePlugins: ignoreStringPlugins(markdownConfig.rehypePlugins),
+ remarkRehype: markdownConfig.remarkRehype as any ?? {},
+ };
+}
function applyDefaultOptions({
options,
diff --git a/packages/integrations/mdx/src/plugins.ts b/packages/integrations/mdx/src/plugins.ts
index 7d475a7f3..850911077 100644
--- a/packages/integrations/mdx/src/plugins.ts
+++ b/packages/integrations/mdx/src/plugins.ts
@@ -4,12 +4,12 @@ import {
safelyGetAstroData,
} from '@astrojs/markdown-remark/dist/internal.js';
import { nodeTypes } from '@mdx-js/mdx';
-import type { PluggableList } from '@mdx-js/mdx/lib/core.js';
import type { Options as MdxRollupPluginOptions } from '@mdx-js/rollup';
+import type { PluggableList } from '@mdx-js/mdx/lib/core.js';
import type { AstroConfig } from 'astro';
import type { Literal, MemberExpression } from 'estree';
import { visit as estreeVisit } from 'estree-util-visit';
-import { bold, yellow } from 'kleur/colors';
+import type { Image } from 'mdast';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
import remarkSmartypants from 'remark-smartypants';
@@ -21,6 +21,9 @@ import remarkPrism from './remark-prism.js';
import remarkShiki from './remark-shiki.js';
import { jsToTreeNode } from './utils.js';
+// Skip nonessential plugins during performance benchmark runs
+const isPerformanceBenchmark = Boolean(process.env.ASTRO_PERFORMANCE_BENCHMARK);
+
export function recmaInjectImportMetaEnvPlugin({
importMetaEnv,
}: {
@@ -99,21 +102,25 @@ export async function getRemarkPlugins(
): Promise<MdxRollupPluginOptions['remarkPlugins']> {
let remarkPlugins: PluggableList = [];
- if (mdxOptions.gfm) {
- remarkPlugins.push(remarkGfm);
- }
- if (mdxOptions.smartypants) {
- remarkPlugins.push(remarkSmartypants);
+ if (!isPerformanceBenchmark) {
+ if (mdxOptions.gfm) {
+ remarkPlugins.push(remarkGfm);
+ }
+ if (mdxOptions.smartypants) {
+ remarkPlugins.push(remarkSmartypants);
+ }
}
- remarkPlugins = [...remarkPlugins, ...ignoreStringPlugins(mdxOptions.remarkPlugins)];
+ remarkPlugins = [...remarkPlugins, ...mdxOptions.remarkPlugins];
- // Apply syntax highlighters after user plugins to match `markdown/remark` behavior
- if (mdxOptions.syntaxHighlight === 'shiki') {
- remarkPlugins.push([await remarkShiki(mdxOptions.shikiConfig)]);
- }
- if (mdxOptions.syntaxHighlight === 'prism') {
- remarkPlugins.push(remarkPrism);
+ if (!isPerformanceBenchmark) {
+ // Apply syntax highlighters after user plugins to match `markdown/remark` behavior
+ if (mdxOptions.syntaxHighlight === 'shiki') {
+ remarkPlugins.push([await remarkShiki(mdxOptions.shikiConfig)]);
+ }
+ if (mdxOptions.syntaxHighlight === 'prism') {
+ remarkPlugins.push(remarkPrism);
+ }
}
return remarkPlugins;
@@ -129,39 +136,16 @@ export function getRehypePlugins(mdxOptions: MdxOptions): MdxRollupPluginOptions
rehypePlugins = [
...rehypePlugins,
- ...ignoreStringPlugins(mdxOptions.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.
- rehypeHeadingIds,
- rehypeInjectHeadingsExport,
+ ...(isPerformanceBenchmark ? [] : [rehypeHeadingIds, rehypeInjectHeadingsExport]),
// computed from `astro.data.frontmatter` in VFile data
rehypeApplyFrontmatterExport,
];
return rehypePlugins;
}
-function ignoreStringPlugins(plugins: any[]) {
- let validPlugins: PluggableList = [];
- let hasInvalidPlugin = false;
- for (const plugin of plugins) {
- if (typeof plugin === 'string') {
- console.warn(yellow(`[MDX] ${bold(plugin)} not applied.`));
- hasInvalidPlugin = true;
- } else if (Array.isArray(plugin) && typeof plugin[0] === 'string') {
- console.warn(yellow(`[MDX] ${bold(plugin[0])} not applied.`));
- hasInvalidPlugin = true;
- } else {
- validPlugins.push(plugin);
- }
- }
- if (hasInvalidPlugin) {
- console.warn(
- `To inherit Markdown plugins in MDX, please use explicit imports in your config instead of "strings." See Markdown docs: https://docs.astro.build/en/guides/markdown-content/#markdown-plugins`
- );
- }
- return validPlugins;
-}
-
/**
* Check if estree entry is "import.meta.env.VARIABLE"
* If it is, return the variable name (i.e. "VARIABLE")
diff --git a/packages/integrations/mdx/src/utils.ts b/packages/integrations/mdx/src/utils.ts
index 766fef5ae..a76186292 100644
--- a/packages/integrations/mdx/src/utils.ts
+++ b/packages/integrations/mdx/src/utils.ts
@@ -1,7 +1,9 @@
import type { Options as AcornOpts } from 'acorn';
import { parse } from 'acorn';
import type { AstroConfig, SSRError } from 'astro';
+import { bold, yellow } from 'kleur/colors';
import matter from 'gray-matter';
+import type { PluggableList } from '@mdx-js/mdx/lib/core.js';
import type { MdxjsEsm } from 'mdast-util-mdx';
function appendForwardSlash(path: string) {
@@ -82,3 +84,25 @@ export function jsToTreeNode(
},
};
}
+
+export function ignoreStringPlugins(plugins: any[]): PluggableList {
+ let validPlugins: PluggableList = [];
+ let hasInvalidPlugin = false;
+ for (const plugin of plugins) {
+ if (typeof plugin === 'string') {
+ console.warn(yellow(`[MDX] ${bold(plugin)} not applied.`));
+ hasInvalidPlugin = true;
+ } else if (Array.isArray(plugin) && typeof plugin[0] === 'string') {
+ console.warn(yellow(`[MDX] ${bold(plugin[0])} not applied.`));
+ hasInvalidPlugin = true;
+ } else {
+ validPlugins.push(plugin);
+ }
+ }
+ if (hasInvalidPlugin) {
+ console.warn(
+ `To inherit Markdown plugins in MDX, please use explicit imports in your config instead of "strings." See Markdown docs: https://docs.astro.build/en/guides/markdown-content/#markdown-plugins`
+ );
+ }
+ return validPlugins;
+}