feat: add experimental jsx support

This commit is contained in:
Nate Moore 2022-06-28 21:02:28 -04:00
parent 660abd3dee
commit b1b5072b60
4 changed files with 29 additions and 12 deletions

View file

@ -52,6 +52,7 @@ const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = {
experimental: { experimental: {
ssr: false, ssr: false,
integrations: false, integrations: false,
jsx: false,
}, },
}; };
@ -224,6 +225,7 @@ export const AstroConfigSchema = z.object({
.object({ .object({
ssr: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.ssr), ssr: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.ssr),
integrations: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.integrations), integrations: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.integrations),
jsx: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.jsx),
}) })
.optional() .optional()
.default({}), .default({}),
@ -339,20 +341,22 @@ export async function validateConfig(
const result = { const result = {
...(await AstroConfigRelativeSchema.parseAsync(userConfig)), ...(await AstroConfigRelativeSchema.parseAsync(userConfig)),
_ctx: { _ctx: {
pageExtensions: [], pageExtensions: [] as string[],
scripts: [], scripts: [],
renderers: [], renderers: [],
injectedRoutes: [], injectedRoutes: [],
adapter: undefined, adapter: undefined,
}, },
}; };
if (result.experimental.jsx) {
result._ctx.pageExtensions.push('.jsx', '.tsx');
}
if ( if (
// TODO: expose @astrojs/mdx package result.experimental.jsx || result.integrations.find((integration) => integration.name === '@astrojs/mdx')
result.integrations.find((integration) => integration.name === '@astrojs/mdx')
) { ) {
// Enable default JSX integration // Enable default JSX integration
const { default: jsxRenderer } = await import('../jsx/renderer.js'); const { default: jsxRenderer } = await import('../jsx/renderer.js');
(result._ctx.renderers as any[]).push(jsxRenderer); (result._ctx.renderers as any[]).unshift(jsxRenderer);
} }
// Final-Pass Validation (perform checks that require the full config object) // Final-Pass Validation (perform checks that require the full config object)

View file

@ -140,11 +140,5 @@ export async function render(opts: RenderOptions): Promise<Response> {
ssr, ssr,
}); });
if (!Component.isAstroComponentFactory) {
const props: Record<string, any> = { ...(pageProps ?? {}), 'server:root': true };
const html = await renderComponent(result, Component.name, Component, props, null);
return new Response(html.toString(), result.response);
} else {
return await renderPage(result, Component, pageProps, null); return await renderPage(result, Component, pageProps, null);
} }
}

View file

@ -694,10 +694,25 @@ export async function renderPage(
props: any, props: any,
children: any children: any
): Promise<Response> { ): Promise<Response> {
let iterable: AsyncIterable<any>;
if (!componentFactory.isAstroComponentFactory) {
const pageProps: Record<string, any> = { ...(props ?? {}), 'server:root': true };
const output = await renderComponent(result, componentFactory.name, componentFactory, pageProps, null);
let html = output.toString()
if (!/<!doctype html/i.test(html)) {
html = `<!DOCTYPE html>\n${await maybeRenderHead(result)}${html}`;
}
return new Response(html, {
headers: new Headers([
['Content-Type', 'text/html; charset=utf-8'],
['Content-Length', `${Buffer.byteLength(html, 'utf-8')}`]
])
});
}
const factoryReturnValue = await componentFactory(result, props, children); const factoryReturnValue = await componentFactory(result, props, children);
if (isAstroComponent(factoryReturnValue)) { if (isAstroComponent(factoryReturnValue)) {
let iterable = renderAstroComponent(factoryReturnValue); iterable = renderAstroComponent(factoryReturnValue);
let stream = new ReadableStream({ let stream = new ReadableStream({
start(controller) { start(controller) {
async function read() { async function read() {

View file

@ -176,6 +176,10 @@ export default function jsx({ config, logging }: AstroPluginJSXOptions): Plugin
} }
} }
if (!importSource && config.experimental.jsx && jsxRenderers.has('astro')) {
importSource = 'astro';
}
// if JSX renderer found, then use that // if JSX renderer found, then use that
if (importSource) { if (importSource) {
const jsxRenderer = jsxRenderers.get(importSource); const jsxRenderer = jsxRenderers.get(importSource);