Repository: withastro/astro
File: packages/astro/src/runtime/server/jsx.ts (TypeScript)

Code before:
}

async function renderJSXVNode(result: SSRResult, vnode: AstroVNode): Promise<any> {
	if (isVNode(vnode)) {
		// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
		switch (true) {
			case !vnode.type: {
				throw new Error(`Unable to render ${result.pathname} because it contains an undefined Component!
Did you forget to import the component or is it possible there is a typo?`);
			}
			case (vnode.type as any) === Symbol.for('astro:fragment'):
				return renderJSX(result, vnode.props.children);
			case isAstroComponentFactory(vnode.type): {
				let props: Record<string, any> = {};
				let slots: Record<string, any> = {};
				for (const [key, value] of Object.entries(vnode.props ?? {})) {
					if (key === 'children' || (value && typeof value === 'object' && value['$$slot'])) {
						slots[key === 'children' ? 'default' : key] = () => renderJSX(result, value);
					} else {
						props[key] = value;
					}
				}
				const str = await renderTemplateResultToString(
					result,
					renderTemplate`${await renderComponent(result, vnode.type.name, vnode.type, props, slots)}`,
				);
				if (str instanceof Response) {
					throw str;
				}
				const html = markHTMLString(str);
				return html;
			}
			case !vnode.type && (vnode.type as any) !== 0:
				return '';
			case typeof vnode.type === 'string' && vnode.type !== ClientOnlyPlaceholder:
				return markHTMLString(await renderElement(result, vnode.type as string, vnode.props ?? {}));
		}

		if (vnode.type) {
			if (typeof vnode.type === 'function' && vnode.props['server:root']) {
				const output = await vnode.type(vnode.props ?? {});
				return await renderJSX(result, output);
			}
			if (typeof vnode.type === 'function') {
				if (vnode.props[hasTriedRenderComponentSymbol]) {
					// omitting compiler-internals from user components
					delete vnode.props[hasTriedRenderComponentSymbol];
					const output = await vnode.type(vnode.props ?? {});
					if (output?.[AstroJSX] || !output) {
						return await renderJSXVNode(result, output);
					} else {

Review comment (refactor):
`renderAstroComponent` is not exposed so I slightly refactored `renderToString` to expose the underlying render template logic

Code after:
async function renderJSXVNode(result: SSRResult, vnode: AstroVNode): Promise<any> {
	if (isVNode(vnode)) {
		// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
		switch (true) {
			case !vnode.type: {
				throw new Error(`Unable to render ${result.pathname} because it contains an undefined Component!
Did you forget to import the component or is it possible there is a typo?`);
			}
			case (vnode.type as any) === Symbol.for('astro:fragment'):
				return renderJSX(result, vnode.props.children);
			case isAstroComponentFactory(vnode.type): {
				let props: Record<string, any> = {};
				let slots: Record<string, any> = {};
				for (const [key, value] of Object.entries(vnode.props ?? {})) {
					if (key === 'children' || (value && typeof value === 'object' && value['$$slot'])) {
						slots[key === 'children' ? 'default' : key] = () => renderJSX(result, value);
					} else {
						props[key] = value;
					}
				}
				// We don't use renderToString because it doesn't contain the server island script handling
				const str = await renderComponentToString(
					result,
					vnode.type.name,
					vnode.type,
					props,
					slots,
				);
				const html = markHTMLString(str);
				return html;
			}
			case !vnode.type && (vnode.type as any) !== 0:
				return '';
			case typeof vnode.type === 'string' && vnode.type !== ClientOnlyPlaceholder:
				return markHTMLString(await renderElement(result, vnode.type as string, vnode.props ?? {}));
		}

		if (vnode.type) {
			if (typeof vnode.type === 'function' && vnode.props['server:root']) {
				const output = await vnode.type(vnode.props ?? {});
				return await renderJSX(result, output);
			}
			if (typeof vnode.type === 'function') {
				if (vnode.props[hasTriedRenderComponentSymbol]) {
					// omitting compiler-internals from user components
					delete vnode.props[hasTriedRenderComponentSymbol];
					const output = await vnode.type(vnode.props ?? {});
					if (output?.[AstroJSX] || !output) {
						return await renderJSXVNode(result, output);
					} else {
						return;