Skip to content

Commit 799f6f3

Browse files
authored
Refactor MDX transformJSX handling (#10688)
1 parent 4ea042c commit 799f6f3

File tree

10 files changed

+198
-216
lines changed

10 files changed

+198
-216
lines changed

.changeset/four-pants-juggle.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"astro": patch
3+
---
4+
5+
Marks renderer `jsxImportSource` and `jsxTransformOptions` options as deprecated as they are no longer used since Astro 3.0

packages/astro/src/@types/astro.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2577,9 +2577,9 @@ export interface AstroRenderer {
25772577
clientEntrypoint?: string;
25782578
/** Import entrypoint for the server/build/ssr renderer. */
25792579
serverEntrypoint: string;
2580-
/** JSX identifier (e.g. 'react' or 'solid-js') */
2580+
/** @deprecated Vite plugins should transform the JSX instead */
25812581
jsxImportSource?: string;
2582-
/** Babel transform options */
2582+
/** @deprecated Vite plugins should transform the JSX instead */
25832583
jsxTransformOptions?: JSXTransformFn;
25842584
}
25852585

packages/astro/src/core/create-vite.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export async function createVite(
137137
envVitePlugin({ settings }),
138138
markdownVitePlugin({ settings, logger }),
139139
htmlVitePlugin(),
140-
mdxVitePlugin({ settings, logger }),
140+
mdxVitePlugin(),
141141
astroPostprocessVitePlugin(),
142142
astroIntegrationsContainerPlugin({ settings, logger }),
143143
astroScriptsPageSSRPlugin({ settings }),

packages/astro/src/jsx/renderer.ts

+5-13
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
1-
const renderer = {
1+
import type { AstroRenderer } from '../@types/astro.js';
2+
import { jsxTransformOptions } from './transform-options.js';
3+
4+
const renderer: AstroRenderer = {
25
name: 'astro:jsx',
36
serverEntrypoint: 'astro/jsx/server.js',
47
jsxImportSource: 'astro',
5-
jsxTransformOptions: async () => {
6-
// @ts-expect-error types not found
7-
const plugin = await import('@babel/plugin-transform-react-jsx');
8-
const jsx = plugin.default?.default ?? plugin.default;
9-
const { default: astroJSX } = await import('./babel.js');
10-
return {
11-
plugins: [
12-
astroJSX(),
13-
jsx({}, { throwIfNamespace: false, runtime: 'automatic', importSource: 'astro' }),
14-
],
15-
};
16-
},
8+
jsxTransformOptions,
179
};
1810

1911
export default renderer;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { JSXTransformConfig } from '../@types/astro.js';
2+
3+
export async function jsxTransformOptions(): Promise<JSXTransformConfig> {
4+
// @ts-expect-error types not found
5+
const plugin = await import('@babel/plugin-transform-react-jsx');
6+
const jsx = plugin.default?.default ?? plugin.default;
7+
const { default: astroJSX } = await import('./babel.js');
8+
return {
9+
plugins: [
10+
astroJSX(),
11+
jsx({}, { throwIfNamespace: false, runtime: 'automatic', importSource: 'astro' }),
12+
],
13+
};
14+
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# vite-plugin-jsx
1+
# vite-plugin-mdx
22

3-
Modifies Vite’s built-in JSX behavior to allow for React, Preact, and Solid.js to coexist and all use `.jsx` and `.tsx` extensions.
3+
Handles transforming MDX via the `astro:jsx` renderer.
+5-92
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,19 @@
1-
import type { TransformResult } from 'rollup';
2-
import { type Plugin, type ResolvedConfig, transformWithEsbuild } from 'vite';
3-
import type { AstroRenderer, AstroSettings } from '../@types/astro.js';
4-
import type { Logger } from '../core/logger/core.js';
5-
import type { PluginMetadata } from '../vite-plugin-astro/types.js';
6-
7-
import babel from '@babel/core';
1+
import { type Plugin, transformWithEsbuild } from 'vite';
82
import { CONTENT_FLAG, PROPAGATED_ASSET_FLAG } from '../content/index.js';
93
import { astroEntryPrefix } from '../core/build/plugins/plugin-component-entry.js';
104
import { removeQueryString } from '../core/path.js';
11-
import tagExportsPlugin from './tag.js';
12-
13-
interface TransformJSXOptions {
14-
code: string;
15-
id: string;
16-
mode: string;
17-
renderer: AstroRenderer;
18-
ssr: boolean;
19-
root: URL;
20-
}
21-
22-
async function transformJSX({
23-
code,
24-
mode,
25-
id,
26-
ssr,
27-
renderer,
28-
root,
29-
}: TransformJSXOptions): Promise<TransformResult> {
30-
const { jsxTransformOptions } = renderer;
31-
const options = await jsxTransformOptions!({ mode, ssr });
32-
const plugins = [...(options.plugins || [])];
33-
if (ssr) {
34-
plugins.push(await tagExportsPlugin({ rendererName: renderer.name, root }));
35-
}
36-
const result = await babel.transformAsync(code, {
37-
presets: options.presets,
38-
plugins,
39-
cwd: process.cwd(),
40-
filename: id,
41-
ast: false,
42-
compact: false,
43-
sourceMaps: true,
44-
configFile: false,
45-
babelrc: false,
46-
inputSourceMap: options.inputSourceMap,
47-
});
48-
// TODO: Be more strict about bad return values here.
49-
// Should we throw an error instead? Should we never return `{code: ""}`?
50-
if (!result) return null;
51-
52-
if (renderer.name === 'astro:jsx') {
53-
const { astro } = result.metadata as unknown as PluginMetadata;
54-
return {
55-
code: result.code || '',
56-
map: result.map,
57-
meta: {
58-
astro,
59-
vite: {
60-
// Setting this vite metadata to `ts` causes Vite to resolve .js
61-
// extensions to .ts files.
62-
lang: 'ts',
63-
},
64-
},
65-
};
66-
}
67-
68-
return {
69-
code: result.code || '',
70-
map: result.map,
71-
};
72-
}
73-
74-
interface AstroPluginJSXOptions {
75-
settings: AstroSettings;
76-
logger: Logger;
77-
}
5+
import { transformJSX } from './transform-jsx.js';
786

797
// Format inspired by https://github.com/vitejs/vite/blob/main/packages/vite/src/node/constants.ts#L54
808
const SPECIAL_QUERY_REGEX = new RegExp(
819
`[?&](?:worker|sharedworker|raw|url|${CONTENT_FLAG}|${PROPAGATED_ASSET_FLAG})\\b`
8210
);
8311

84-
/** Use Astro config to allow for alternate or multiple JSX renderers (by default Vite will assume React) */
85-
export default function mdxVitePlugin({ settings }: AstroPluginJSXOptions): Plugin {
86-
let viteConfig: ResolvedConfig;
87-
// A reference to Astro's internal JSX renderer.
88-
let astroJSXRenderer: AstroRenderer;
89-
12+
// TODO: Move this Vite plugin into `@astrojs/mdx` in Astro 5
13+
export default function mdxVitePlugin(): Plugin {
9014
return {
9115
name: 'astro:jsx',
9216
enforce: 'pre', // run transforms before other plugins
93-
async configResolved(resolvedConfig) {
94-
viteConfig = resolvedConfig;
95-
astroJSXRenderer = settings.renderers.find((r) => r.jsxImportSource === 'astro')!;
96-
},
9717
async transform(code, id, opts) {
9818
// Skip special queries and astro entries. We skip astro entries here as we know it doesn't contain
9919
// JSX code, and also because we can't detect the import source to apply JSX transforms.
@@ -117,14 +37,7 @@ export default function mdxVitePlugin({ settings }: AstroPluginJSXOptions): Plug
11737
},
11838
},
11939
});
120-
return transformJSX({
121-
code: jsxCode,
122-
id,
123-
renderer: astroJSXRenderer,
124-
mode: viteConfig.mode,
125-
ssr: Boolean(opts?.ssr),
126-
root: settings.config.root,
127-
});
40+
return await transformJSX(jsxCode, id, opts?.ssr);
12841
},
12942
};
13043
}

0 commit comments

Comments
 (0)