summaryrefslogtreecommitdiff
path: root/packages/integrations/solid/src/server.ts
blob: bd50d8d7731b81a85ec82f64db9c8b02d7a5eb25 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import type { RendererContext } from './types';
import { renderToString, ssr, createComponent } from 'solid-js/web';
import { getContext, incrementId } from './context.js';

const slotName = (str: string) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase());

function check(this: RendererContext, Component: any, props: Record<string, any>, children: any) {
	if (typeof Component !== 'function') return false;
	const { html } = renderToStaticMarkup.call(this, Component, props, children);
	return typeof html === 'string';
}

function renderToStaticMarkup(this: RendererContext, Component: any, props: Record<string, any>, { default: children, ...slotted }: any, metadata?: undefined | Record<string, any>) {
	const renderId = metadata?.hydrate ? incrementId(getContext(this.result)) : '';

	const html = renderToString(() => {
		const slots: Record<string, any> = {};
		for (const [key, value] of Object.entries(slotted)) {
			const name = slotName(key);
			slots[name] = ssr(`<astro-slot name="${name}">${value}</astro-slot>`);
		}
		// Note: create newProps to avoid mutating `props` before they are serialized
		const newProps = {
			...props,
			...slots,
			// In Solid SSR mode, `ssr` creates the expected structure for `children`.
			children: children != null ? ssr(`<astro-slot>${children}</astro-slot>`) : children,
		};

		return createComponent(Component, newProps);
	}, {
		renderId
	});
	return {
		attrs: {
			'data-solid-render-id': renderId
		},
		html
	};
}

export default {
	check,
	renderToStaticMarkup,
};