@estjs/server 0.0.15 → 0.0.16-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.d.ts CHANGED
@@ -1,50 +1,109 @@
1
1
  import { ComponentProps, ComponentFn } from '@estjs/template';
2
+ export { getHydrationKey, resetHydrationKey } from '@estjs/template';
2
3
  export { escapeHTML } from '@estjs/shared';
3
4
 
4
5
  /**
5
- * Render a component to HTML string
6
- * @param {ComponentFn} component - the component to render
7
- * @param {ComponentProps} props - the props to pass to the component
8
- * @returns {string} the rendered HTML string
6
+ * SSR rendering context.
7
+
8
+ */
9
+ interface SSRContext {
10
+ /**
11
+ * Map of teleport target → concatenated HTML string. The caller is
12
+ * responsible for inlining each entry into the final document
13
+ * (e.g. by replacing a placeholder in a shell template).
14
+ */
15
+ teleports: Record<string, string>;
16
+ /**
17
+ * Free-form key/value bag for user-defined per-render metadata
18
+ * (e.g. collected `<head>` tags, status codes, response headers).
19
+ */
20
+ [key: string]: unknown;
21
+ }
22
+ /**
23
+ * Create an empty SSR context with all collection slots initialised.
9
24
  */
10
- declare function renderToString<P extends ComponentProps = ComponentProps>(component: ComponentFn<P>, props?: P | ComponentProps): string;
25
+ declare function createSSRContext(): SSRContext;
26
+ /**
27
+ * Get the current SSR context, if any. Returns `null` when called outside of
28
+ * a `renderToString` invocation, or when the caller did not pass a context.
29
+ */
30
+ declare function getSSRContext(): SSRContext | null;
31
+
11
32
  /**
12
- * Render template with components (used by babel plugin in SSG mode)
13
- * @param {string[]} templates - the template fragments
14
- * @param {string} hydrationKey - the hydration key
15
- * @param {...string[]} components - the rendered component strings
16
- * @returns {string} the rendered HTML string
33
+ * Render a component to HTML string.
34
+ *
35
+ * Each invocation runs inside its own root scope so that `provide()` calls
36
+ * stay isolated between independent `renderToString` calls.
37
+ *
38
+ * @param component - The component to render.
39
+ * @param props - The props to pass to the component.
40
+ * @param context - Optional {@link SSRContext} that collects out-of-tree
41
+ * render output (currently: `Portal`/`Teleport` content). The same context
42
+ * is visible to nested `createSSGComponent` calls; the caller integrates
43
+ * `context.teleports[selector]` into the final document.
44
+ * @returns {string} The rendered HTML string.
45
+ */
46
+ declare function renderToString<P extends ComponentProps = ComponentProps>(component: ComponentFn<P>, props?: P | ComponentProps, context?: SSRContext | null): string;
47
+ /**
48
+ * Render template with components (used by babel plugin in SSG mode).
49
+ *
50
+ * @param templates - The template fragments.
51
+ * @param hydrationKey - The hydration key.
52
+ * @param components - The rendered component strings.
53
+ * @returns {string} The rendered HTML string.
17
54
  */
18
55
  declare function render(templates: string[], hydrationKey: string, ...components: string[]): string;
19
56
  /**
20
- * Create a SSG component (renders component to string)
21
- * @param {ComponentFn} component - the component to create
22
- * @param {ComponentProps} props - the props to pass to the component
23
- * @returns {string} the rendered component as a string
57
+ * Async variant of {@link renderToString}. Awaits component results so that
58
+ * `async` components and promise-returning expressions can participate in SSR.
59
+ *
60
+ * The awaited value is passed through the same {@link convertToString}
61
+ * pipeline as the synchronous path, which itself transparently awaits any
62
+ * nested promises (arrays of promises, promise-returning thunks, etc.).
63
+ */
64
+ declare function renderToStringAsync<P extends ComponentProps = ComponentProps>(component: ComponentFn<P>, props?: P | ComponentProps, context?: SSRContext | null): Promise<string>;
65
+ /**
66
+ * Create a SSG component (renders component to string).
67
+ *
68
+ * The component executes inside a child scope that inherits from the current
69
+ * active scope, so `inject()` calls can resolve values from ancestor
70
+ * `provide()` calls, and `provide()` inside the component is scoped to it.
71
+ *
72
+ * @param component - The component to create.
73
+ * @param props - The props to pass to the component.
74
+ * @returns {string} The rendered component as a string.
24
75
  */
25
76
  declare function createSSGComponent<P extends ComponentProps = ComponentProps>(component: ComponentFn<P>, props?: P | ComponentProps): string;
26
77
 
27
78
  /**
28
- * Convert content to string for SSR output
79
+ * Convert content to string for SSR output.
29
80
  *
30
- * @param content - the content to convert
31
- * @param isSvg - whether the content is SVG
32
- * @returns the content as a string
81
+ * @param content - The content to convert.
82
+ * @param isSvg - Whether the content is SVG.
83
+ * @returns {string} The content as a string.
33
84
  */
34
85
  declare function convertToString(content: unknown, isSvg?: boolean): string;
35
86
  /**
36
- * Add hydration attributes to HTML content
87
+ * Convert child-expression content to escaped text for SSR output.
37
88
  *
38
- * @param htmlContent - the html content
39
- * @param hydrationId - the hydration id
40
- * @returns the html content with hydration attributes
89
+ * JSX expression children have text semantics, so primitives must be escaped
90
+ * before interpolation into the surrounding HTML template.
91
+ */
92
+ declare function convertTextChildToString(content: unknown): string;
93
+ /**
94
+ * Add hydration attributes to HTML content.
95
+ *
96
+ * @param htmlContent - The html content.
97
+ * @param hydrationId - The hydration id.
98
+ * @returns {string} The html content with hydration attributes.
41
99
  */
42
100
  declare function addAttributes(htmlContent: string, hydrationId: string): string;
43
101
 
44
102
  /**
45
103
  * Normalize component properties
46
104
  *
47
- * Special handling for class and style attributes, converting them to normalized format
105
+ * Special handling for class and style attributes, converting them to normalized format.
106
+ * Returns a new object when normalization is needed, preserving the original.
48
107
  *
49
108
  * @param props - Original component properties
50
109
  * @returns Normalized component properties
@@ -61,9 +120,90 @@ declare function normalizeProps(props: Record<string, any> | null): Record<strin
61
120
  *
62
121
  * @param attrName - Attribute name
63
122
  * @param attrValue - Attribute value
64
- * @param hydrationId - Hydration ID (for client-side reuse)
65
123
  * @returns Formatted HTML attribute string
66
124
  */
67
- declare function setSSGAttr(attrName: string, attrValue: any, hydrationId: string): string;
125
+ declare function setSSGAttr(attrName: string, attrValue: any): string;
126
+
127
+ /**
128
+ * Render a single attribute as an HTML attribute string.
129
+ *
130
+ * @param name - The name of the attribute.
131
+ * @param value - The value of the attribute.
132
+ * @returns {string} The rendered attribute string (e.g., ` name="value"`).
133
+ */
134
+ declare function ssrAttr(name: string, value: unknown): string;
135
+ /**
136
+ * Render a `class` attribute as an HTML attribute string.
137
+ *
138
+ * @param value - The class value (string, object, or array).
139
+ * @returns {string} The rendered class attribute string.
140
+ */
141
+ declare function ssrClass(value: unknown): string;
142
+ /**
143
+ * Render a `style` attribute as an HTML attribute string.
144
+ *
145
+ * @param value - The style value (string or object).
146
+ * @returns {string} The rendered style attribute string.
147
+ */
148
+ declare function ssrStyle(value: unknown): string;
149
+ /**
150
+ * Render a spread of props as HTML attribute strings.
151
+ * Skips event handlers and special keys.
152
+ *
153
+ * @param props - The props object to spread.
154
+ * @returns {string} The rendered attribute strings.
155
+ */
156
+ declare function ssrSpread(props: Record<string, unknown>): string;
157
+
158
+ interface SSRComponentProps {
159
+ children?: unknown;
160
+ [key: string]: unknown;
161
+ }
162
+ /**
163
+ * SSR Fragment — returns children converted to a string.
164
+ */
165
+ declare function Fragment(props: SSRComponentProps): string;
166
+ interface SSRPortalProps extends SSRComponentProps {
167
+ /**
168
+ * Teleport target — only CSS selector strings are meaningful on the server.
169
+ * Element references are silently inlined (they have no server-side meaning).
170
+ */
171
+ target?: string;
172
+ /**
173
+ * When truthy, children render inline instead of being teleported.
174
+ * The babel plugin resolves reactive getters before reaching the component,
175
+ * so only a plain boolean is needed on the server.
176
+ */
177
+ disabled?: boolean | (() => boolean);
178
+ }
179
+ declare const TELEPORT_CALLSITE_ANCHOR = "<!--teleport-anchor-->";
180
+ declare const TELEPORT_BLOCK_START = "<!--teleport-start-->";
181
+ declare const TELEPORT_BLOCK_END = "<!--teleport-end-->";
182
+ /**
183
+ * SSR Portal — collects teleported content into `ctx.teleports[target]`.
184
+ *
185
+ * Emits `<!--teleport-anchor-->` at the call site and wraps children with
186
+ * `<!--teleport-start-->...<!--teleport-end-->` in the target buffer.
187
+ * Disabled / no-target / no-context falls back to inline rendering.
188
+ */
189
+ declare function Portal(props: SSRPortalProps): string;
190
+ /**
191
+ * SSR Suspense — renders children when available, otherwise the fallback slot.
192
+ */
193
+ declare function Suspense(props: SSRComponentProps & {
194
+ fallback?: unknown;
195
+ }): string;
196
+ interface SSRForProps<T> {
197
+ each: T[] | {
198
+ value: T[];
199
+ } | (() => T[]);
200
+ children: (item: T, index: number) => unknown;
201
+ key?: (item: T, index: number) => unknown;
202
+ fallback?: unknown;
203
+ }
204
+ /**
205
+ * SSR For — maps each item through the render function and joins the output.
206
+ */
207
+ declare function For<T>(props: SSRForProps<T>): string;
68
208
 
69
- export { addAttributes, convertToString, createSSGComponent, normalizeProps, render, renderToString, setSSGAttr };
209
+ export { For, Fragment, Portal, type SSRComponentProps, type SSRContext, type SSRForProps, type SSRPortalProps, Suspense, TELEPORT_BLOCK_END, TELEPORT_BLOCK_START, TELEPORT_CALLSITE_ANCHOR, addAttributes, convertTextChildToString, convertToString, createSSGComponent, createSSRContext, getSSRContext, normalizeProps, render, renderToString, renderToStringAsync, setSSGAttr, ssrAttr, ssrClass, ssrSpread, ssrStyle };
@@ -0,0 +1,401 @@
1
+ 'use strict';
2
+
3
+ var shared = require('@estjs/shared');
4
+ var template = require('@estjs/template');
5
+ var internal = require('@estjs/template/internal');
6
+ var async_hooks = require('async_hooks');
7
+ var signals = require('@estjs/signals');
8
+
9
+ var __defProp = Object.defineProperty;
10
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
13
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
+ var __spreadValues = (a, b) => {
15
+ for (var prop in b || (b = {}))
16
+ if (__hasOwnProp.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
18
+ if (__getOwnPropSymbols)
19
+ for (var prop of __getOwnPropSymbols(b)) {
20
+ if (__propIsEnum.call(b, prop))
21
+ __defNormalProp(a, prop, b[prop]);
22
+ }
23
+ return a;
24
+ };
25
+ var __async = (__this, __arguments, generator) => {
26
+ return new Promise((resolve, reject) => {
27
+ var fulfilled = (value) => {
28
+ try {
29
+ step(generator.next(value));
30
+ } catch (e) {
31
+ reject(e);
32
+ }
33
+ };
34
+ var rejected = (value) => {
35
+ try {
36
+ step(generator.throw(value));
37
+ } catch (e) {
38
+ reject(e);
39
+ }
40
+ };
41
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
42
+ step((generator = generator.apply(__this, __arguments)).next());
43
+ });
44
+ };
45
+ function createSSRContext() {
46
+ return {
47
+ teleports: /* @__PURE__ */ Object.create(null)
48
+ };
49
+ }
50
+ var store = new async_hooks.AsyncLocalStorage();
51
+ function getSSRContext() {
52
+ var _a;
53
+ return (_a = store.getStore()) != null ? _a : null;
54
+ }
55
+ function runWithSSRContext(ctx, fn) {
56
+ return store.run(ctx, fn);
57
+ }
58
+ function convertToString(content, isSvg = false) {
59
+ if (shared.isNil(content)) {
60
+ return "";
61
+ }
62
+ if (shared.isString(content)) {
63
+ return content;
64
+ }
65
+ if (shared.isArray(content)) {
66
+ return content.map((item) => convertToString(item, isSvg)).join("");
67
+ }
68
+ if (shared.isFunction(content)) {
69
+ return convertToString(content(), isSvg);
70
+ }
71
+ return String(content);
72
+ }
73
+ function convertTextChildToString(content) {
74
+ if (content === false || shared.isNil(content)) {
75
+ return "";
76
+ }
77
+ if (shared.isString(content)) {
78
+ return shared.escapeHTML(content);
79
+ }
80
+ if (shared.isArray(content)) {
81
+ return content.map((item) => convertTextChildToString(item)).join("");
82
+ }
83
+ if (shared.isFunction(content)) {
84
+ return convertTextChildToString(content());
85
+ }
86
+ return shared.escapeHTML(String(content));
87
+ }
88
+ var HYDRATION_REWRITE_REGEX = /data-idx="(\d+)"|<!--(\d+)-->/g;
89
+ function injectRootHydrationAttribute(htmlContent, hydrationId) {
90
+ const tagStart = htmlContent.indexOf("<");
91
+ if (tagStart === -1) {
92
+ return htmlContent;
93
+ }
94
+ let quote;
95
+ for (let i = tagStart + 1; i < htmlContent.length; i++) {
96
+ const char = htmlContent[i];
97
+ if (quote) {
98
+ if (char === quote) {
99
+ quote = void 0;
100
+ }
101
+ continue;
102
+ }
103
+ if (char === '"' || char === "'") {
104
+ quote = char;
105
+ continue;
106
+ }
107
+ if (char === ">") {
108
+ let insertAt = i;
109
+ for (let j = i - 1; j > tagStart; j--) {
110
+ const prev = htmlContent[j];
111
+ if (prev === " " || prev === "\n" || prev === " " || prev === "\r") {
112
+ continue;
113
+ }
114
+ if (prev === "/") {
115
+ insertAt = j;
116
+ }
117
+ break;
118
+ }
119
+ return `${htmlContent.slice(0, insertAt)} data-hk="${hydrationId}"${htmlContent.slice(insertAt)}`;
120
+ }
121
+ }
122
+ return htmlContent;
123
+ }
124
+ function addAttributes(htmlContent, hydrationId) {
125
+ return injectRootHydrationAttribute(htmlContent, hydrationId).replaceAll(
126
+ HYDRATION_REWRITE_REGEX,
127
+ (_match, dataIdx, commentBody) => dataIdx !== void 0 ? `data-idx="${hydrationId}-${dataIdx}"` : `<!--${hydrationId}-${commentBody}-->`
128
+ );
129
+ }
130
+
131
+ // src/render.ts
132
+ function runInFreshScope(fn, parent = internal.getActiveScope()) {
133
+ const scope = internal.createScope(parent);
134
+ try {
135
+ return internal.runWithScope(scope, fn);
136
+ } finally {
137
+ internal.disposeScope(scope);
138
+ }
139
+ }
140
+ function renderToString(component, props = {}, context = null) {
141
+ if (!shared.isFunction(component)) {
142
+ shared.error("Component must be a function");
143
+ return "";
144
+ }
145
+ template.resetHydrationKey();
146
+ const result = runWithSSRContext(
147
+ context,
148
+ () => runInFreshScope(() => component(props), null)
149
+ );
150
+ if (shared.isPromise(result)) {
151
+ shared.error("renderToString received a Promise \u2014 use renderToStringAsync for async components.");
152
+ }
153
+ return convertToString(result);
154
+ }
155
+ function render(templates, hydrationKey, ...components) {
156
+ const templateLen = templates.length;
157
+ const componentLen = components.length;
158
+ let content = "";
159
+ for (let i = 0; i < templateLen; i++) {
160
+ content += templates[i];
161
+ if (i < componentLen && components[i]) {
162
+ content += convertToString(components[i]);
163
+ }
164
+ }
165
+ return addAttributes(content, hydrationKey);
166
+ }
167
+ function renderToStringAsync(_0) {
168
+ return __async(this, arguments, function* (component, props = {}, context = null) {
169
+ if (!shared.isFunction(component)) {
170
+ shared.error("Component must be a function");
171
+ return "";
172
+ }
173
+ template.resetHydrationKey();
174
+ const scope = internal.createScope(null);
175
+ try {
176
+ return yield runWithSSRContext(context, () => __async(null, null, function* () {
177
+ let result = internal.runWithScope(scope, () => component(props));
178
+ if (shared.isPromise(result)) {
179
+ result = yield result;
180
+ }
181
+ return convertToStringAsync(result);
182
+ }));
183
+ } finally {
184
+ internal.disposeScope(scope);
185
+ }
186
+ });
187
+ }
188
+ function convertToStringAsync(content) {
189
+ return __async(this, null, function* () {
190
+ if (shared.isPromise(content)) {
191
+ return convertToStringAsync(yield content);
192
+ }
193
+ if (Array.isArray(content)) {
194
+ const parts = yield Promise.all(content.map((c) => convertToStringAsync(c)));
195
+ return parts.join("");
196
+ }
197
+ if (shared.isFunction(content)) {
198
+ return convertToStringAsync(content());
199
+ }
200
+ return convertToString(content);
201
+ });
202
+ }
203
+ function createSSGComponent(component, props = {}) {
204
+ if (!shared.isFunction(component)) {
205
+ shared.error("createSSGComponent: Component is not a function");
206
+ return "";
207
+ }
208
+ const result = runInFreshScope(() => component(props));
209
+ return convertToString(result);
210
+ }
211
+ function normalizeProps(props) {
212
+ if (!props) {
213
+ return null;
214
+ }
215
+ const { class: className, style } = props;
216
+ const needsClassNorm = className && !shared.isString(className);
217
+ const needsStyleNorm = !!style;
218
+ if (!needsClassNorm && !needsStyleNorm) {
219
+ return props;
220
+ }
221
+ const result = __spreadValues({}, props);
222
+ if (needsClassNorm) {
223
+ result.class = shared.normalizeClassName(className);
224
+ }
225
+ if (needsStyleNorm) {
226
+ result.style = shared.normalizeStyle(style);
227
+ }
228
+ return result;
229
+ }
230
+ function setSSGAttr(attrName, attrValue) {
231
+ if (signals.isSignal(attrValue) || signals.isComputed(attrValue)) {
232
+ return setSSGAttr(attrName, attrValue.value);
233
+ }
234
+ if (!attrValue && attrValue !== 0) {
235
+ return "";
236
+ }
237
+ if (attrName === "style") {
238
+ const normalizedStyle = shared.normalizeStyle(attrValue);
239
+ if (!normalizedStyle) {
240
+ return "";
241
+ }
242
+ if (shared.isString(normalizedStyle)) {
243
+ return ` style="${normalizedStyle}"`;
244
+ }
245
+ return ` style="${shared.styleToString(normalizedStyle)}"`;
246
+ }
247
+ if (attrName === "class") {
248
+ const normalizedClassName = shared.normalizeClassName(attrValue);
249
+ return normalizedClassName ? ` class="${normalizedClassName}"` : "";
250
+ }
251
+ if (attrName.startsWith("on")) {
252
+ return "";
253
+ }
254
+ if (attrValue === true) {
255
+ return ` ${attrName}`;
256
+ }
257
+ return ` ${attrName}="${shared.escapeHTML(String(attrValue))}"`;
258
+ }
259
+ function ssrAttr(name, value) {
260
+ if (shared.isNil(value) || value === false) return "";
261
+ if (value === true) return ` ${name}`;
262
+ return ` ${name}="${shared.escapeHTML(String(value))}"`;
263
+ }
264
+ function ssrClass(value) {
265
+ const normalized = normalizeClassSSR(value);
266
+ if (!normalized) return "";
267
+ return ` class="${shared.escapeHTML(normalized)}"`;
268
+ }
269
+ function ssrStyle(value) {
270
+ if (shared.isNil(value)) return "";
271
+ if (shared.isString(value)) return value ? ` style="${shared.escapeHTML(value)}"` : "";
272
+ if (shared.isObject(value)) {
273
+ const obj = value;
274
+ const parts = [];
275
+ for (const key in obj) {
276
+ const v = obj[key];
277
+ if (v != null && v !== false) {
278
+ const prop = key.startsWith("--") ? key : camelToKebab(key);
279
+ parts.push(`${prop}:${shared.escapeHTML(String(v))}`);
280
+ }
281
+ }
282
+ if (!parts.length) return "";
283
+ return ` style="${parts.join(";")}"`;
284
+ }
285
+ return "";
286
+ }
287
+ function ssrSpread(props) {
288
+ if (!props || !shared.isObject(props)) return "";
289
+ let out = "";
290
+ for (const key in props) {
291
+ if (key === "children" || key === "ref" || key.startsWith("on")) continue;
292
+ if (key === "class" || key === "className") {
293
+ out += ssrClass(props[key]);
294
+ } else if (key === "style") {
295
+ out += ssrStyle(props[key]);
296
+ } else {
297
+ out += ssrAttr(key, props[key]);
298
+ }
299
+ }
300
+ return out;
301
+ }
302
+ function normalizeClassSSR(value) {
303
+ if (shared.isNil(value) || value === false) return "";
304
+ if (shared.isString(value)) return value;
305
+ if (shared.isArray(value)) {
306
+ return value.map(normalizeClassSSR).filter(Boolean).join(" ");
307
+ }
308
+ if (shared.isObject(value)) {
309
+ const obj = value;
310
+ return Object.keys(obj).filter((k) => Boolean(obj[k])).join(" ");
311
+ }
312
+ return String(value);
313
+ }
314
+ var UPPER_RE = /[A-Z]/g;
315
+ function camelToKebab(str) {
316
+ return str.replaceAll(UPPER_RE, (m) => `-${m.toLowerCase()}`);
317
+ }
318
+ function Fragment(props) {
319
+ return convertToString(props.children);
320
+ }
321
+ var TELEPORT_CALLSITE_ANCHOR = "<!--teleport-anchor-->";
322
+ var TELEPORT_BLOCK_START = "<!--teleport-start-->";
323
+ var TELEPORT_BLOCK_END = "<!--teleport-end-->";
324
+ function Portal(props) {
325
+ var _a;
326
+ const { target, children } = props;
327
+ const rendered = convertToString(children);
328
+ const disabled = shared.isFunction(props.disabled) ? !!props.disabled() : !!props.disabled;
329
+ if (disabled || !target) return rendered;
330
+ const ctx = getSSRContext();
331
+ if (!ctx) return rendered;
332
+ if (!shared.isString(target)) {
333
+ {
334
+ shared.warn("[Portal] SSR only supports string selector targets; rendering inline.");
335
+ }
336
+ return rendered;
337
+ }
338
+ ctx.teleports[target] = ((_a = ctx.teleports[target]) != null ? _a : "") + TELEPORT_BLOCK_START + rendered + TELEPORT_BLOCK_END;
339
+ return TELEPORT_CALLSITE_ANCHOR;
340
+ }
341
+ function Suspense(props) {
342
+ const { children, fallback } = props;
343
+ return shared.isNil(children) ? convertToString(fallback) : convertToString(children);
344
+ }
345
+ function resolveList(input) {
346
+ var _a, _b;
347
+ if (shared.isNil(input)) return [];
348
+ if (shared.isObject(input) && "value" in input) {
349
+ return (_a = input.value) != null ? _a : [];
350
+ }
351
+ if (shared.isFunction(input)) {
352
+ return (_b = input()) != null ? _b : [];
353
+ }
354
+ return input;
355
+ }
356
+ function For(props) {
357
+ const list = resolveList(props.each);
358
+ if (list.length === 0) {
359
+ return convertToString(props.fallback);
360
+ }
361
+ const render2 = props.children;
362
+ if (!shared.isFunction(render2)) return "";
363
+ return list.map((item, i) => convertToString(render2(item, i))).join("");
364
+ }
365
+
366
+ Object.defineProperty(exports, "escapeHTML", {
367
+ enumerable: true,
368
+ get: function () { return shared.escapeHTML; }
369
+ });
370
+ Object.defineProperty(exports, "getHydrationKey", {
371
+ enumerable: true,
372
+ get: function () { return template.getHydrationKey; }
373
+ });
374
+ Object.defineProperty(exports, "resetHydrationKey", {
375
+ enumerable: true,
376
+ get: function () { return template.resetHydrationKey; }
377
+ });
378
+ exports.For = For;
379
+ exports.Fragment = Fragment;
380
+ exports.Portal = Portal;
381
+ exports.Suspense = Suspense;
382
+ exports.TELEPORT_BLOCK_END = TELEPORT_BLOCK_END;
383
+ exports.TELEPORT_BLOCK_START = TELEPORT_BLOCK_START;
384
+ exports.TELEPORT_CALLSITE_ANCHOR = TELEPORT_CALLSITE_ANCHOR;
385
+ exports.addAttributes = addAttributes;
386
+ exports.convertTextChildToString = convertTextChildToString;
387
+ exports.convertToString = convertToString;
388
+ exports.createSSGComponent = createSSGComponent;
389
+ exports.createSSRContext = createSSRContext;
390
+ exports.getSSRContext = getSSRContext;
391
+ exports.normalizeProps = normalizeProps;
392
+ exports.render = render;
393
+ exports.renderToString = renderToString;
394
+ exports.renderToStringAsync = renderToStringAsync;
395
+ exports.setSSGAttr = setSSGAttr;
396
+ exports.ssrAttr = ssrAttr;
397
+ exports.ssrClass = ssrClass;
398
+ exports.ssrSpread = ssrSpread;
399
+ exports.ssrStyle = ssrStyle;
400
+ //# sourceMappingURL=server.dev.cjs.js.map
401
+ //# sourceMappingURL=server.dev.cjs.js.map