From a3e95dbeb04bb09e4253f9b690c1627b3ce7e90d Mon Sep 17 00:00:00 2001
From: Bjorn Lu <bjornlu.dev@gmail.com>
Date: Tue, 23 Apr 2024 23:24:34 +0800
Subject: [PATCH 1/2] Move MDX Vite plugin to new file (#10854)

---
 packages/integrations/mdx/src/index.ts        | 93 +------------------
 .../integrations/mdx/src/vite-plugin-mdx.ts   | 88 ++++++++++++++++++
 2 files changed, 93 insertions(+), 88 deletions(-)
 create mode 100644 packages/integrations/mdx/src/vite-plugin-mdx.ts

diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts
index e48d0d8f1979..fc1d92da48ca 100644
--- a/packages/integrations/mdx/src/index.ts
+++ b/packages/integrations/mdx/src/index.ts
@@ -1,16 +1,14 @@
 import fs from 'node:fs/promises';
 import { fileURLToPath } from 'node:url';
-import { markdownConfigDefaults, setVfileFrontmatter } from '@astrojs/markdown-remark';
-import type { AstroIntegration, ContentEntryType, HookParameters, SSRError } from 'astro';
+import { markdownConfigDefaults } from '@astrojs/markdown-remark';
+import type { AstroIntegration, ContentEntryType, HookParameters } from 'astro';
 import astroJSXRenderer from 'astro/jsx/renderer.js';
 import type { Options as RemarkRehypeOptions } from 'remark-rehype';
 import type { PluggableList } from 'unified';
-import { VFile } from 'vfile';
-import type { Plugin as VitePlugin } from 'vite';
-import { createMdxProcessor } from './plugins.js';
 import type { OptimizeOptions } from './rehype-optimize-static.js';
-import { getFileInfo, ignoreStringPlugins, parseFrontmatter } from './utils.js';
+import { ignoreStringPlugins, parseFrontmatter } from './utils.js';
 import { vitePluginMdxPostprocess } from './vite-plugin-mdx-postprocess.js';
+import { vitePluginMdx } from './vite-plugin-mdx.js';
 
 export type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlugins' | 'rehypePlugins'> & {
 	extendMarkdownConfig: boolean;
@@ -70,90 +68,9 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
 					),
 				});
 
-				let processor: ReturnType<typeof createMdxProcessor> | undefined;
-
 				updateConfig({
 					vite: {
-						plugins: [
-							{
-								name: '@mdx-js/rollup',
-								enforce: 'pre',
-								buildEnd() {
-									processor = undefined;
-								},
-								configResolved(resolved) {
-									processor = createMdxProcessor(mdxOptions, {
-										sourcemap: !!resolved.build.sourcemap,
-									});
-
-									// HACK: move ourselves before Astro's JSX plugin to transform things in the right order
-									const jsxPluginIndex = resolved.plugins.findIndex((p) => p.name === 'astro:jsx');
-									if (jsxPluginIndex !== -1) {
-										const myPluginIndex = resolved.plugins.findIndex(
-											(p) => p.name === '@mdx-js/rollup'
-										);
-										if (myPluginIndex !== -1) {
-											const myPlugin = resolved.plugins[myPluginIndex];
-											// @ts-ignore-error ignore readonly annotation
-											resolved.plugins.splice(myPluginIndex, 1);
-											// @ts-ignore-error ignore readonly annotation
-											resolved.plugins.splice(jsxPluginIndex, 0, myPlugin);
-										}
-									}
-								},
-								async resolveId(source, importer, options) {
-									if (importer?.endsWith('.mdx') && source[0] !== '/') {
-										let resolved = await this.resolve(source, importer, options);
-										if (!resolved) resolved = await this.resolve('./' + source, importer, options);
-										return resolved;
-									}
-								},
-								// Override transform to alter code before MDX compilation
-								// ex. inject layouts
-								async transform(_, id) {
-									if (!id.endsWith('.mdx')) return;
-
-									// Read code from file manually to prevent Vite from parsing `import.meta.env` expressions
-									const { fileId } = getFileInfo(id, config);
-									const code = await fs.readFile(fileId, 'utf-8');
-
-									const { data: frontmatter, content: pageContent } = parseFrontmatter(code, id);
-
-									const vfile = new VFile({ value: pageContent, path: id });
-									// Ensure `data.astro` is available to all remark plugins
-									setVfileFrontmatter(vfile, frontmatter);
-
-									// `processor` is initialized in `configResolved`, and removed in `buildEnd`. `transform`
-									// should be called in between those two lifecycle, so this error should never happen
-									if (!processor) {
-										return this.error(
-											'MDX processor is not initialized. This is an internal error. Please file an issue.'
-										);
-									}
-
-									try {
-										const compiled = await processor.process(vfile);
-
-										return {
-											code: String(compiled.value),
-											map: compiled.map,
-										};
-									} catch (e: any) {
-										const err: SSRError = e;
-
-										// For some reason MDX puts the error location in the error's name, not very useful for us.
-										err.name = 'MDXError';
-										err.loc = { file: fileId, line: e.line, column: e.column };
-
-										// For another some reason, MDX doesn't include a stack trace. Weird
-										Error.captureStackTrace(err);
-
-										throw err;
-									}
-								},
-							},
-							vitePluginMdxPostprocess(config),
-						] as VitePlugin[],
+						plugins: [vitePluginMdx(config, mdxOptions), vitePluginMdxPostprocess(config)],
 					},
 				});
 			},
diff --git a/packages/integrations/mdx/src/vite-plugin-mdx.ts b/packages/integrations/mdx/src/vite-plugin-mdx.ts
new file mode 100644
index 000000000000..0185f37fb1a0
--- /dev/null
+++ b/packages/integrations/mdx/src/vite-plugin-mdx.ts
@@ -0,0 +1,88 @@
+import fs from 'node:fs/promises';
+import { setVfileFrontmatter } from '@astrojs/markdown-remark';
+import type { AstroConfig, SSRError } from 'astro';
+import { VFile } from 'vfile';
+import type { Plugin } from 'vite';
+import { createMdxProcessor } from './plugins.js';
+import { getFileInfo, parseFrontmatter } from './utils.js';
+import type { MdxOptions } from './index.js';
+
+export function vitePluginMdx(astroConfig: AstroConfig, mdxOptions: MdxOptions): Plugin {
+	let processor: ReturnType<typeof createMdxProcessor> | undefined;
+
+	return {
+		name: '@mdx-js/rollup',
+		enforce: 'pre',
+		buildEnd() {
+			processor = undefined;
+		},
+		configResolved(resolved) {
+			processor = createMdxProcessor(mdxOptions, {
+				sourcemap: !!resolved.build.sourcemap,
+			});
+
+			// HACK: move ourselves before Astro's JSX plugin to transform things in the right order
+			const jsxPluginIndex = resolved.plugins.findIndex((p) => p.name === 'astro:jsx');
+			if (jsxPluginIndex !== -1) {
+				const myPluginIndex = resolved.plugins.findIndex((p) => p.name === '@mdx-js/rollup');
+				if (myPluginIndex !== -1) {
+					const myPlugin = resolved.plugins[myPluginIndex];
+					// @ts-ignore-error ignore readonly annotation
+					resolved.plugins.splice(myPluginIndex, 1);
+					// @ts-ignore-error ignore readonly annotation
+					resolved.plugins.splice(jsxPluginIndex, 0, myPlugin);
+				}
+			}
+		},
+		async resolveId(source, importer, options) {
+			if (importer?.endsWith('.mdx') && source[0] !== '/') {
+				let resolved = await this.resolve(source, importer, options);
+				if (!resolved) resolved = await this.resolve('./' + source, importer, options);
+				return resolved;
+			}
+		},
+		// Override transform to alter code before MDX compilation
+		// ex. inject layouts
+		async transform(_, id) {
+			if (!id.endsWith('.mdx')) return;
+
+			// Read code from file manually to prevent Vite from parsing `import.meta.env` expressions
+			const { fileId } = getFileInfo(id, astroConfig);
+			const code = await fs.readFile(fileId, 'utf-8');
+
+			const { data: frontmatter, content: pageContent } = parseFrontmatter(code, id);
+
+			const vfile = new VFile({ value: pageContent, path: id });
+			// Ensure `data.astro` is available to all remark plugins
+			setVfileFrontmatter(vfile, frontmatter);
+
+			// `processor` is initialized in `configResolved`, and removed in `buildEnd`. `transform`
+			// should be called in between those two lifecycle, so this error should never happen
+			if (!processor) {
+				return this.error(
+					'MDX processor is not initialized. This is an internal error. Please file an issue.'
+				);
+			}
+
+			try {
+				const compiled = await processor.process(vfile);
+
+				return {
+					code: String(compiled.value),
+					map: compiled.map,
+				};
+			} catch (e: any) {
+				const err: SSRError = e;
+
+				// For some reason MDX puts the error location in the error's name, not very useful for us.
+				err.name = 'MDXError';
+				err.loc = { file: fileId, line: e.line, column: e.column };
+
+				// For another some reason, MDX doesn't include a stack trace. Weird
+				Error.captureStackTrace(err);
+
+				throw err;
+			}
+		},
+	};
+}

From d7dff648241b23b235f7060249de0fe015411bc3 Mon Sep 17 00:00:00 2001
From: Bjorn Lu <bluwy@users.noreply.github.com>
Date: Tue, 23 Apr 2024 15:25:25 +0000
Subject: [PATCH 2/2] [ci] format

---
 packages/integrations/mdx/src/vite-plugin-mdx.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/integrations/mdx/src/vite-plugin-mdx.ts b/packages/integrations/mdx/src/vite-plugin-mdx.ts
index 0185f37fb1a0..6f2ec2cc487a 100644
--- a/packages/integrations/mdx/src/vite-plugin-mdx.ts
+++ b/packages/integrations/mdx/src/vite-plugin-mdx.ts
@@ -3,9 +3,9 @@ import { setVfileFrontmatter } from '@astrojs/markdown-remark';
 import type { AstroConfig, SSRError } from 'astro';
 import { VFile } from 'vfile';
 import type { Plugin } from 'vite';
+import type { MdxOptions } from './index.js';
 import { createMdxProcessor } from './plugins.js';
 import { getFileInfo, parseFrontmatter } from './utils.js';
-import type { MdxOptions } from './index.js';
 
 export function vitePluginMdx(astroConfig: AstroConfig, mdxOptions: MdxOptions): Plugin {
 	let processor: ReturnType<typeof createMdxProcessor> | undefined;