sinwan 0.1.0 → 1.0.0
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/README.md +66 -39
- package/dist/cjs/index.development.js +1624 -961
- package/dist/cjs/index.development.js.map +21 -18
- package/dist/cjs/index.production.min.js +2 -2
- package/dist/cjs/index.production.min.js.map +21 -18
- package/dist/cjs/jsx/jsx-dev-runtime.development.js +6 -16
- package/dist/cjs/jsx/jsx-dev-runtime.development.js.map +3 -3
- package/dist/cjs/jsx/jsx-dev-runtime.production.min.js +2 -2
- package/dist/cjs/jsx/jsx-dev-runtime.production.min.js.map +3 -3
- package/dist/cjs/jsx/jsx-runtime.development.js +6 -16
- package/dist/cjs/jsx/jsx-runtime.development.js.map +3 -3
- package/dist/cjs/jsx/jsx-runtime.production.min.js +2 -2
- package/dist/cjs/jsx/jsx-runtime.production.min.js.map +3 -3
- package/dist/cjs/renderer/index.development.js +1175 -0
- package/dist/cjs/renderer/index.development.js.map +24 -0
- package/dist/cjs/renderer/index.production.min.js +3 -0
- package/dist/cjs/renderer/index.production.min.js.map +24 -0
- package/dist/cjs/server/index.development.js +665 -329
- package/dist/cjs/server/index.development.js.map +11 -10
- package/dist/cjs/server/index.production.min.js +2 -2
- package/dist/cjs/server/index.production.min.js.map +11 -10
- package/dist/component/control-flow.d.ts +18 -0
- package/dist/component/control-flow.d.ts.map +1 -0
- package/dist/component/index.d.ts +3 -1
- package/dist/component/index.d.ts.map +1 -1
- package/dist/component/instance.d.ts +7 -1
- package/dist/component/instance.d.ts.map +1 -1
- package/dist/component/lifecycle.d.ts +2 -1
- package/dist/component/lifecycle.d.ts.map +1 -1
- package/dist/component/provide-inject.d.ts +11 -5
- package/dist/component/provide-inject.d.ts.map +1 -1
- package/dist/esm/index.development.js +1301 -660
- package/dist/esm/index.development.js.map +21 -18
- package/dist/esm/index.production.min.js +2 -2
- package/dist/esm/index.production.min.js.map +21 -18
- package/dist/esm/jsx/jsx-dev-runtime.development.js +6 -16
- package/dist/esm/jsx/jsx-dev-runtime.development.js.map +3 -3
- package/dist/esm/jsx/jsx-dev-runtime.production.min.js +2 -2
- package/dist/esm/jsx/jsx-dev-runtime.production.min.js.map +3 -3
- package/dist/esm/jsx/jsx-runtime.development.js +6 -16
- package/dist/esm/jsx/jsx-runtime.development.js.map +3 -3
- package/dist/esm/jsx/jsx-runtime.production.min.js +2 -2
- package/dist/esm/jsx/jsx-runtime.production.min.js.map +3 -3
- package/dist/esm/renderer/index.development.js +1124 -0
- package/dist/esm/renderer/index.development.js.map +24 -0
- package/dist/esm/renderer/index.production.min.js +4 -0
- package/dist/esm/renderer/index.production.min.js.map +24 -0
- package/dist/esm/server/index.development.js +665 -329
- package/dist/esm/server/index.development.js.map +11 -10
- package/dist/esm/server/index.production.min.js +2 -2
- package/dist/esm/server/index.production.min.js.map +11 -10
- package/dist/hydration/walk.d.ts.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/jsx/jsx-runtime.d.ts +13 -0
- package/dist/jsx/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx/jsx-types.d.ts +122 -57
- package/dist/jsx/jsx-types.d.ts.map +1 -1
- package/dist/renderer/attributes.d.ts.map +1 -1
- package/dist/renderer/dom-ops.d.ts +4 -1
- package/dist/renderer/dom-ops.d.ts.map +1 -1
- package/dist/renderer/index.d.ts +1 -1
- package/dist/renderer/index.d.ts.map +1 -1
- package/dist/renderer/mount.d.ts +2 -5
- package/dist/renderer/mount.d.ts.map +1 -1
- package/dist/renderer/render-children.d.ts +2 -2
- package/dist/renderer/render-children.d.ts.map +1 -1
- package/dist/renderer/render-control-flow.d.ts +13 -0
- package/dist/renderer/render-control-flow.d.ts.map +1 -0
- package/dist/renderer/render-element.d.ts +1 -1
- package/dist/renderer/render-element.d.ts.map +1 -1
- package/dist/renderer/types.d.ts +2 -0
- package/dist/renderer/types.d.ts.map +1 -1
- package/dist/renderer/unmount.d.ts +20 -0
- package/dist/renderer/unmount.d.ts.map +1 -0
- package/dist/renderer.d.ts +1 -0
- package/dist/renderer.js +7 -0
- package/dist/renderer.mjs +4 -0
- package/dist/server/hydration-markers.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/renderer.d.ts.map +1 -1
- package/dist/server/stream.d.ts +9 -1
- package/dist/server/stream.d.ts.map +1 -1
- package/dist/types.d.ts +8 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +15 -1
|
@@ -40,22 +40,12 @@ function buildElement(type, props, children) {
|
|
|
40
40
|
if (type === Fragment) {
|
|
41
41
|
return { tag: "", props: {}, children };
|
|
42
42
|
}
|
|
43
|
-
if (typeof type === "function") {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return result2;
|
|
48
|
-
}
|
|
49
|
-
return { tag: "", props: {}, children: normalizeChildren(result2) };
|
|
50
|
-
}
|
|
51
|
-
const result = type(props);
|
|
52
|
-
if (result && typeof result === "object" && "tag" in result) {
|
|
53
|
-
return result;
|
|
43
|
+
if (typeof type === "function" || typeof type === "string") {
|
|
44
|
+
const finalProps = props ?? {};
|
|
45
|
+
if (children.length > 0 && finalProps.children === undefined) {
|
|
46
|
+
finalProps.children = children.length === 1 ? children[0] : children;
|
|
54
47
|
}
|
|
55
|
-
return { tag:
|
|
56
|
-
}
|
|
57
|
-
if (typeof type === "string") {
|
|
58
|
-
return { tag: type, props: props || {}, children };
|
|
48
|
+
return { tag: type, props: finalProps, children };
|
|
59
49
|
}
|
|
60
50
|
return { tag: "", props: {}, children };
|
|
61
51
|
}
|
|
@@ -109,221 +99,6 @@ function isSafeHtml(value) {
|
|
|
109
99
|
return value instanceof HtmlEscapedString;
|
|
110
100
|
}
|
|
111
101
|
|
|
112
|
-
// src/server/renderer.ts
|
|
113
|
-
var componentCache = new WeakMap;
|
|
114
|
-
var pageRegistry = new Map;
|
|
115
|
-
function registerPage(name, page) {
|
|
116
|
-
pageRegistry.set(name, page);
|
|
117
|
-
}
|
|
118
|
-
function getPage(name) {
|
|
119
|
-
return pageRegistry.get(name);
|
|
120
|
-
}
|
|
121
|
-
function hasPage(name) {
|
|
122
|
-
return pageRegistry.has(name);
|
|
123
|
-
}
|
|
124
|
-
async function renderPage(name, data) {
|
|
125
|
-
const page = getPage(name);
|
|
126
|
-
if (!page) {
|
|
127
|
-
throw new Error(`Page "${name}" not found in registry`);
|
|
128
|
-
}
|
|
129
|
-
const element = await page(data);
|
|
130
|
-
return renderToString(element);
|
|
131
|
-
}
|
|
132
|
-
async function renderToString(node) {
|
|
133
|
-
if (node == null || typeof node === "boolean") {
|
|
134
|
-
return "";
|
|
135
|
-
}
|
|
136
|
-
if (typeof node === "string") {
|
|
137
|
-
return escapeHtml(node);
|
|
138
|
-
}
|
|
139
|
-
if (typeof node === "number") {
|
|
140
|
-
return String(node);
|
|
141
|
-
}
|
|
142
|
-
if (node instanceof HtmlEscapedString) {
|
|
143
|
-
return node.value;
|
|
144
|
-
}
|
|
145
|
-
if (Array.isArray(node)) {
|
|
146
|
-
const results = await Promise.all(node.map((child) => renderToString(child)));
|
|
147
|
-
return results.join("");
|
|
148
|
-
}
|
|
149
|
-
if (node instanceof Promise) {
|
|
150
|
-
return renderElement(await node);
|
|
151
|
-
}
|
|
152
|
-
return renderElement(node);
|
|
153
|
-
}
|
|
154
|
-
async function renderElement(element) {
|
|
155
|
-
const { tag, props, children } = element;
|
|
156
|
-
if (typeof tag === "function") {
|
|
157
|
-
const result = await tag(props);
|
|
158
|
-
return renderToString(result);
|
|
159
|
-
}
|
|
160
|
-
if (typeof tag === "string") {
|
|
161
|
-
return renderIntrinsicElement(tag, props, children);
|
|
162
|
-
}
|
|
163
|
-
return renderToString(children);
|
|
164
|
-
}
|
|
165
|
-
var VOID_ELEMENTS2 = new Set([
|
|
166
|
-
"area",
|
|
167
|
-
"base",
|
|
168
|
-
"br",
|
|
169
|
-
"col",
|
|
170
|
-
"embed",
|
|
171
|
-
"hr",
|
|
172
|
-
"img",
|
|
173
|
-
"input",
|
|
174
|
-
"link",
|
|
175
|
-
"meta",
|
|
176
|
-
"param",
|
|
177
|
-
"source",
|
|
178
|
-
"track",
|
|
179
|
-
"wbr"
|
|
180
|
-
]);
|
|
181
|
-
async function renderIntrinsicElement(tag, props, children) {
|
|
182
|
-
const attrs = renderAttributes(props);
|
|
183
|
-
if (VOID_ELEMENTS2.has(tag)) {
|
|
184
|
-
return attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
185
|
-
}
|
|
186
|
-
const childrenHtml = await renderChildren(children, props);
|
|
187
|
-
return attrs ? `<${tag}${attrs}>${childrenHtml}</${tag}>` : `<${tag}>${childrenHtml}</${tag}>`;
|
|
188
|
-
}
|
|
189
|
-
function renderAttributes(props) {
|
|
190
|
-
let attrs = "";
|
|
191
|
-
for (const [key, value] of Object.entries(props)) {
|
|
192
|
-
if (key === "children")
|
|
193
|
-
continue;
|
|
194
|
-
if (value == null || value === false)
|
|
195
|
-
continue;
|
|
196
|
-
if (value === true) {
|
|
197
|
-
attrs += ` ${key}`;
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
if (key === "dangerouslySetInnerHTML") {
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
const attrName = key === "className" ? "class" : key;
|
|
204
|
-
const finalName = attrName === "htmlFor" ? "for" : attrName;
|
|
205
|
-
const attrValue = escapeHtml(String(value));
|
|
206
|
-
attrs += ` ${finalName}="${attrValue}"`;
|
|
207
|
-
}
|
|
208
|
-
return attrs;
|
|
209
|
-
}
|
|
210
|
-
async function renderChildren(children, props) {
|
|
211
|
-
const dangerous = props.dangerouslySetInnerHTML;
|
|
212
|
-
if (dangerous && typeof dangerous.__html === "string") {
|
|
213
|
-
return dangerous.__html;
|
|
214
|
-
}
|
|
215
|
-
return renderToString(children);
|
|
216
|
-
}
|
|
217
|
-
function isSlots(children) {
|
|
218
|
-
return children != null && typeof children === "object" && !Array.isArray(children) && !(children instanceof HtmlEscapedString);
|
|
219
|
-
}
|
|
220
|
-
// src/server/stream.ts
|
|
221
|
-
var VOID_ELEMENTS3 = new Set([
|
|
222
|
-
"area",
|
|
223
|
-
"base",
|
|
224
|
-
"br",
|
|
225
|
-
"col",
|
|
226
|
-
"embed",
|
|
227
|
-
"hr",
|
|
228
|
-
"img",
|
|
229
|
-
"input",
|
|
230
|
-
"link",
|
|
231
|
-
"meta",
|
|
232
|
-
"param",
|
|
233
|
-
"source",
|
|
234
|
-
"track",
|
|
235
|
-
"wbr"
|
|
236
|
-
]);
|
|
237
|
-
function streamPage(page, data) {
|
|
238
|
-
const encoder = new TextEncoder;
|
|
239
|
-
return new ReadableStream({
|
|
240
|
-
async start(controller) {
|
|
241
|
-
try {
|
|
242
|
-
const element = await page(data);
|
|
243
|
-
await streamNode(element, controller, encoder);
|
|
244
|
-
controller.close();
|
|
245
|
-
} catch (error) {
|
|
246
|
-
controller.error(error);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
async function streamNode(node, controller, encoder) {
|
|
252
|
-
if (node == null || typeof node === "boolean") {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
if (typeof node === "string") {
|
|
256
|
-
controller.enqueue(encoder.encode(escapeHtml(node)));
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
if (typeof node === "number") {
|
|
260
|
-
controller.enqueue(encoder.encode(String(node)));
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
if (node instanceof HtmlEscapedString) {
|
|
264
|
-
controller.enqueue(encoder.encode(node.value));
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
if (Array.isArray(node)) {
|
|
268
|
-
for (const child of node) {
|
|
269
|
-
await streamNode(child, controller, encoder);
|
|
270
|
-
}
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
if (node instanceof Promise) {
|
|
274
|
-
const resolved = await node;
|
|
275
|
-
await streamElement(resolved, controller, encoder);
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
await streamElement(node, controller, encoder);
|
|
279
|
-
}
|
|
280
|
-
async function streamElement(element, controller, encoder) {
|
|
281
|
-
const { tag, props, children } = element;
|
|
282
|
-
if (typeof tag === "function") {
|
|
283
|
-
const result = await tag(props);
|
|
284
|
-
await streamNode(result, controller, encoder);
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
if (typeof tag === "string") {
|
|
288
|
-
await streamIntrinsicElement(tag, props, children, controller, encoder);
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
await streamNode(children, controller, encoder);
|
|
292
|
-
}
|
|
293
|
-
async function streamIntrinsicElement(tag, props, children, controller, encoder) {
|
|
294
|
-
const attrs = renderAttributes2(props);
|
|
295
|
-
const dangerous = props.dangerouslySetInnerHTML;
|
|
296
|
-
if (VOID_ELEMENTS3.has(tag)) {
|
|
297
|
-
const html = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
298
|
-
controller.enqueue(encoder.encode(html));
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
const openTag = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
302
|
-
controller.enqueue(encoder.encode(openTag));
|
|
303
|
-
if (dangerous && typeof dangerous.__html === "string") {
|
|
304
|
-
controller.enqueue(encoder.encode(dangerous.__html));
|
|
305
|
-
} else {
|
|
306
|
-
await streamNode(children, controller, encoder);
|
|
307
|
-
}
|
|
308
|
-
controller.enqueue(encoder.encode(`</${tag}>`));
|
|
309
|
-
}
|
|
310
|
-
function renderAttributes2(props) {
|
|
311
|
-
let attrs = "";
|
|
312
|
-
for (const [key, value] of Object.entries(props)) {
|
|
313
|
-
if (key === "children" || key === "dangerouslySetInnerHTML")
|
|
314
|
-
continue;
|
|
315
|
-
if (value == null || value === false)
|
|
316
|
-
continue;
|
|
317
|
-
if (value === true) {
|
|
318
|
-
attrs += ` ${key}`;
|
|
319
|
-
continue;
|
|
320
|
-
}
|
|
321
|
-
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
322
|
-
const attrValue = escapeHtml(String(value));
|
|
323
|
-
attrs += ` ${attrName}="${attrValue}"`;
|
|
324
|
-
}
|
|
325
|
-
return attrs;
|
|
326
|
-
}
|
|
327
102
|
// src/reactivity/scheduler.ts
|
|
328
103
|
var pendingEffects = new Set;
|
|
329
104
|
var flushScheduled = false;
|
|
@@ -566,79 +341,68 @@ function isComputed(value) {
|
|
|
566
341
|
return value != null && typeof value === "object" && COMPUTED_BRAND in value;
|
|
567
342
|
}
|
|
568
343
|
|
|
569
|
-
// src/
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
|
|
344
|
+
// src/renderer/dom-ops.ts
|
|
345
|
+
function createDefaultDOMOps() {
|
|
346
|
+
return {
|
|
347
|
+
createElement(tag) {
|
|
348
|
+
return document.createElement(tag);
|
|
349
|
+
},
|
|
350
|
+
createElementNS(namespace, tag) {
|
|
351
|
+
return document.createElementNS(namespace, tag);
|
|
352
|
+
},
|
|
353
|
+
createTextNode(text) {
|
|
354
|
+
return document.createTextNode(text);
|
|
355
|
+
},
|
|
356
|
+
createComment(text) {
|
|
357
|
+
return document.createComment(text);
|
|
358
|
+
},
|
|
359
|
+
setAttribute(el, key, value) {
|
|
360
|
+
el.setAttribute(key, value);
|
|
361
|
+
},
|
|
362
|
+
removeAttribute(el, key) {
|
|
363
|
+
el.removeAttribute(key);
|
|
364
|
+
},
|
|
365
|
+
setProperty(el, key, value) {
|
|
366
|
+
el[key] = value;
|
|
367
|
+
},
|
|
368
|
+
insertBefore(parent, child, anchor) {
|
|
369
|
+
parent.insertBefore(child, anchor);
|
|
370
|
+
},
|
|
371
|
+
appendChild(parent, child) {
|
|
372
|
+
parent.appendChild(child);
|
|
373
|
+
},
|
|
374
|
+
remove(node) {
|
|
375
|
+
node.parentNode?.removeChild(node);
|
|
376
|
+
},
|
|
377
|
+
setTextContent(node, text) {
|
|
378
|
+
node.data = text;
|
|
379
|
+
},
|
|
380
|
+
addEventListener(el, event, handler) {
|
|
381
|
+
el.addEventListener(event, handler);
|
|
382
|
+
},
|
|
383
|
+
removeEventListener(el, event, handler) {
|
|
384
|
+
el.removeEventListener(event, handler);
|
|
385
|
+
},
|
|
386
|
+
parentNode(node) {
|
|
387
|
+
return node.parentNode;
|
|
388
|
+
},
|
|
389
|
+
nextSibling(node) {
|
|
390
|
+
return node.nextSibling;
|
|
391
|
+
}
|
|
392
|
+
};
|
|
580
393
|
}
|
|
581
|
-
|
|
582
|
-
|
|
394
|
+
var defaultDOMOps = createDefaultDOMOps();
|
|
395
|
+
var domOps = { ...defaultDOMOps };
|
|
396
|
+
function setDOMOps(overrides) {
|
|
397
|
+
Object.assign(domOps, overrides);
|
|
583
398
|
}
|
|
584
|
-
function
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
const idx = parseInt(data.slice(TEXT_MARKER_OPEN.length), 10);
|
|
588
|
-
return Number.isNaN(idx) ? -1 : idx;
|
|
399
|
+
function resetDOMOps() {
|
|
400
|
+
for (const key of Object.keys(domOps)) {
|
|
401
|
+
delete domOps[key];
|
|
589
402
|
}
|
|
590
|
-
|
|
591
|
-
}
|
|
592
|
-
function isTextCloseMarker(node) {
|
|
593
|
-
return node.data === TEXT_MARKER_CLOSE;
|
|
403
|
+
Object.assign(domOps, defaultDOMOps);
|
|
594
404
|
}
|
|
595
405
|
|
|
596
|
-
// src/renderer/dom-ops.ts
|
|
597
|
-
var domOps = {
|
|
598
|
-
createElement(tag) {
|
|
599
|
-
return document.createElement(tag);
|
|
600
|
-
},
|
|
601
|
-
createTextNode(text) {
|
|
602
|
-
return document.createTextNode(text);
|
|
603
|
-
},
|
|
604
|
-
createComment(text) {
|
|
605
|
-
return document.createComment(text);
|
|
606
|
-
},
|
|
607
|
-
setAttribute(el, key, value) {
|
|
608
|
-
el.setAttribute(key, value);
|
|
609
|
-
},
|
|
610
|
-
removeAttribute(el, key) {
|
|
611
|
-
el.removeAttribute(key);
|
|
612
|
-
},
|
|
613
|
-
setProperty(el, key, value) {
|
|
614
|
-
el[key] = value;
|
|
615
|
-
},
|
|
616
|
-
insertBefore(parent, child, anchor) {
|
|
617
|
-
parent.insertBefore(child, anchor);
|
|
618
|
-
},
|
|
619
|
-
appendChild(parent, child) {
|
|
620
|
-
parent.appendChild(child);
|
|
621
|
-
},
|
|
622
|
-
remove(node) {
|
|
623
|
-
node.parentNode?.removeChild(node);
|
|
624
|
-
},
|
|
625
|
-
setTextContent(node, text) {
|
|
626
|
-
node.data = text;
|
|
627
|
-
},
|
|
628
|
-
addEventListener(el, event, handler) {
|
|
629
|
-
el.addEventListener(event, handler);
|
|
630
|
-
},
|
|
631
|
-
removeEventListener(el, event, handler) {
|
|
632
|
-
el.removeEventListener(event, handler);
|
|
633
|
-
},
|
|
634
|
-
parentNode(node) {
|
|
635
|
-
return node.parentNode;
|
|
636
|
-
},
|
|
637
|
-
nextSibling(node) {
|
|
638
|
-
return node.nextSibling;
|
|
639
|
-
}
|
|
640
|
-
};
|
|
641
|
-
|
|
642
406
|
// src/renderer/events.ts
|
|
643
407
|
function isEventProp(key) {
|
|
644
408
|
return key.length > 2 && key[0] === "o" && key[1] === "n" && key[2] >= "A" && key[2] <= "Z";
|
|
@@ -666,24 +430,184 @@ function bindEvents(el, props) {
|
|
|
666
430
|
return cleanups;
|
|
667
431
|
}
|
|
668
432
|
|
|
669
|
-
// src/component/
|
|
670
|
-
var
|
|
671
|
-
|
|
433
|
+
// src/component/control-flow.ts
|
|
434
|
+
var SHOW_TYPE = Symbol.for("Sinwan.Show");
|
|
435
|
+
var FOR_TYPE = Symbol.for("Sinwan.For");
|
|
436
|
+
function Show(props) {
|
|
672
437
|
return {
|
|
673
|
-
|
|
674
|
-
component,
|
|
438
|
+
tag: SHOW_TYPE,
|
|
675
439
|
props,
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
440
|
+
children: []
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function For(props) {
|
|
444
|
+
return {
|
|
445
|
+
tag: FOR_TYPE,
|
|
446
|
+
props,
|
|
447
|
+
children: []
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
function isShowElement(element) {
|
|
451
|
+
return element.tag === SHOW_TYPE;
|
|
452
|
+
}
|
|
453
|
+
function isForElement(element) {
|
|
454
|
+
return element.tag === FOR_TYPE;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// src/server/renderer.ts
|
|
458
|
+
var componentCache = new WeakMap;
|
|
459
|
+
var pageRegistry = new Map;
|
|
460
|
+
function registerPage(name, page) {
|
|
461
|
+
pageRegistry.set(name, page);
|
|
462
|
+
}
|
|
463
|
+
function getPage(name) {
|
|
464
|
+
return pageRegistry.get(name);
|
|
465
|
+
}
|
|
466
|
+
function hasPage(name) {
|
|
467
|
+
return pageRegistry.has(name);
|
|
468
|
+
}
|
|
469
|
+
async function renderPage(name, data) {
|
|
470
|
+
const page = getPage(name);
|
|
471
|
+
if (!page) {
|
|
472
|
+
throw new Error(`Page "${name}" not found in registry`);
|
|
473
|
+
}
|
|
474
|
+
const element = await page(data);
|
|
475
|
+
return renderToString(element);
|
|
476
|
+
}
|
|
477
|
+
async function renderToString(node) {
|
|
478
|
+
if (node == null || typeof node === "boolean") {
|
|
479
|
+
return "";
|
|
480
|
+
}
|
|
481
|
+
if (typeof node === "string") {
|
|
482
|
+
return escapeHtml(node);
|
|
483
|
+
}
|
|
484
|
+
if (typeof node === "number") {
|
|
485
|
+
return String(node);
|
|
486
|
+
}
|
|
487
|
+
if (node instanceof HtmlEscapedString) {
|
|
488
|
+
return node.value;
|
|
489
|
+
}
|
|
490
|
+
if (isSignal(node) || isComputed(node)) {
|
|
491
|
+
return escapeHtml(String(node.value));
|
|
492
|
+
}
|
|
493
|
+
if (Array.isArray(node)) {
|
|
494
|
+
const results = await Promise.all(node.map((child) => renderToString(child)));
|
|
495
|
+
return results.join("");
|
|
496
|
+
}
|
|
497
|
+
if (node instanceof Promise) {
|
|
498
|
+
return renderElement(await node);
|
|
499
|
+
}
|
|
500
|
+
return renderElement(node);
|
|
501
|
+
}
|
|
502
|
+
async function renderElement(element) {
|
|
503
|
+
const { tag, props, children } = element;
|
|
504
|
+
if (isShowElement(element)) {
|
|
505
|
+
const when = readReactive(props.when);
|
|
506
|
+
return renderToString(when ? resolveShowChildren(element, when) : props.fallback);
|
|
507
|
+
}
|
|
508
|
+
if (isForElement(element)) {
|
|
509
|
+
return renderForElement(element);
|
|
510
|
+
}
|
|
511
|
+
if (typeof tag === "function") {
|
|
512
|
+
const result = await tag(props);
|
|
513
|
+
return renderToString(result);
|
|
514
|
+
}
|
|
515
|
+
if (typeof tag === "string") {
|
|
516
|
+
return renderIntrinsicElement(tag, props, children);
|
|
517
|
+
}
|
|
518
|
+
return renderToString(children);
|
|
519
|
+
}
|
|
520
|
+
var VOID_ELEMENTS2 = new Set([
|
|
521
|
+
"area",
|
|
522
|
+
"base",
|
|
523
|
+
"br",
|
|
524
|
+
"col",
|
|
525
|
+
"embed",
|
|
526
|
+
"hr",
|
|
527
|
+
"img",
|
|
528
|
+
"input",
|
|
529
|
+
"link",
|
|
530
|
+
"meta",
|
|
531
|
+
"param",
|
|
532
|
+
"source",
|
|
533
|
+
"track",
|
|
534
|
+
"wbr"
|
|
535
|
+
]);
|
|
536
|
+
async function renderIntrinsicElement(tag, props, children) {
|
|
537
|
+
const attrs = renderAttributes(props);
|
|
538
|
+
if (VOID_ELEMENTS2.has(tag)) {
|
|
539
|
+
return attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
540
|
+
}
|
|
541
|
+
const childrenHtml = await renderChildren(children, props);
|
|
542
|
+
return attrs ? `<${tag}${attrs}>${childrenHtml}</${tag}>` : `<${tag}>${childrenHtml}</${tag}>`;
|
|
543
|
+
}
|
|
544
|
+
function renderAttributes(props) {
|
|
545
|
+
let attrs = "";
|
|
546
|
+
for (const [key, value] of Object.entries(props)) {
|
|
547
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
const resolvedValue = readReactive(value);
|
|
551
|
+
if (resolvedValue == null || resolvedValue === false)
|
|
552
|
+
continue;
|
|
553
|
+
const attrName = key === "className" ? "class" : key;
|
|
554
|
+
const finalName = attrName === "htmlFor" ? "for" : attrName;
|
|
555
|
+
if (resolvedValue === true) {
|
|
556
|
+
attrs += ` ${finalName}`;
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
const attrValue = escapeHtml(String(resolvedValue));
|
|
560
|
+
attrs += ` ${finalName}="${attrValue}"`;
|
|
561
|
+
}
|
|
562
|
+
return attrs;
|
|
563
|
+
}
|
|
564
|
+
async function renderChildren(children, props) {
|
|
565
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
566
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
567
|
+
return dangerous.__html;
|
|
568
|
+
}
|
|
569
|
+
return renderToString(children);
|
|
570
|
+
}
|
|
571
|
+
function isSlots(children) {
|
|
572
|
+
return children != null && typeof children === "object" && !Array.isArray(children) && !(children instanceof HtmlEscapedString);
|
|
573
|
+
}
|
|
574
|
+
async function renderForElement(element) {
|
|
575
|
+
const props = element.props;
|
|
576
|
+
const each = readReactive(props.each);
|
|
577
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
578
|
+
return "";
|
|
579
|
+
}
|
|
580
|
+
const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(item, () => index))));
|
|
581
|
+
return rendered.join("");
|
|
582
|
+
}
|
|
583
|
+
function resolveShowChildren(element, value) {
|
|
584
|
+
const children = element.props.children ?? element.children;
|
|
585
|
+
if (typeof children === "function") {
|
|
586
|
+
return children(value);
|
|
587
|
+
}
|
|
588
|
+
return children;
|
|
589
|
+
}
|
|
590
|
+
function readReactive(value) {
|
|
591
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
592
|
+
}
|
|
593
|
+
// src/component/instance.ts
|
|
594
|
+
var uidCounter = 0;
|
|
595
|
+
function createComponentInstance(component, props, parent) {
|
|
596
|
+
return {
|
|
597
|
+
uid: uidCounter++,
|
|
598
|
+
component,
|
|
599
|
+
props,
|
|
600
|
+
element: null,
|
|
601
|
+
parent,
|
|
602
|
+
children: [],
|
|
603
|
+
effects: [],
|
|
604
|
+
_mountedHooks: [],
|
|
605
|
+
_unmountedHooks: [],
|
|
606
|
+
_updatedHooks: [],
|
|
607
|
+
_errorHooks: [],
|
|
608
|
+
provides: parent ? Object.create(parent.provides) : Object.create(null),
|
|
609
|
+
isMounted: false,
|
|
610
|
+
isUnmounted: false
|
|
687
611
|
};
|
|
688
612
|
}
|
|
689
613
|
var currentInstance = null;
|
|
@@ -695,7 +619,18 @@ function setCurrentInstance(instance) {
|
|
|
695
619
|
currentInstance = instance;
|
|
696
620
|
return prev;
|
|
697
621
|
}
|
|
622
|
+
function withInstance(instance, fn) {
|
|
623
|
+
const prev = setCurrentInstance(instance);
|
|
624
|
+
try {
|
|
625
|
+
return fn();
|
|
626
|
+
} finally {
|
|
627
|
+
setCurrentInstance(prev);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
698
630
|
function fireMountedHooks(instance) {
|
|
631
|
+
if (instance.isUnmounted) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
699
634
|
for (const child of instance.children) {
|
|
700
635
|
fireMountedHooks(child);
|
|
701
636
|
}
|
|
@@ -722,6 +657,24 @@ function fireUnmountedHooks(instance) {
|
|
|
722
657
|
instance.effects.length = 0;
|
|
723
658
|
}
|
|
724
659
|
}
|
|
660
|
+
function fireUpdatedHooks(instance) {
|
|
661
|
+
for (const hook of instance._updatedHooks) {
|
|
662
|
+
hook();
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
var queuedUpdatedHooks = new Set;
|
|
666
|
+
function queueUpdatedHooks(instance) {
|
|
667
|
+
if (!instance || !instance.isMounted || instance.isUnmounted || instance._updatedHooks.length === 0 || queuedUpdatedHooks.has(instance)) {
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
queuedUpdatedHooks.add(instance);
|
|
671
|
+
nextTick(() => {
|
|
672
|
+
queuedUpdatedHooks.delete(instance);
|
|
673
|
+
if (instance.isMounted && !instance.isUnmounted) {
|
|
674
|
+
fireUpdatedHooks(instance);
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
}
|
|
725
678
|
function handleComponentError(instance, err) {
|
|
726
679
|
let current = instance;
|
|
727
680
|
while (current) {
|
|
@@ -736,6 +689,342 @@ function handleComponentError(instance, err) {
|
|
|
736
689
|
console.error("[Sinwan] Unhandled component error:", err);
|
|
737
690
|
}
|
|
738
691
|
|
|
692
|
+
// src/hydration/markers.ts
|
|
693
|
+
var COMP_ID_ATTR = "data-sinwan-id";
|
|
694
|
+
var COMP_ID_PREFIX = "c";
|
|
695
|
+
var TEXT_MARKER_OPEN = "sinwan-t:";
|
|
696
|
+
var TEXT_MARKER_CLOSE = "/sinwan-t";
|
|
697
|
+
var EVENT_ATTR = "data-sinwan-ev";
|
|
698
|
+
function compId(index) {
|
|
699
|
+
return `${COMP_ID_PREFIX}${index}`;
|
|
700
|
+
}
|
|
701
|
+
function textMarkerOpen(index) {
|
|
702
|
+
return `<!--${TEXT_MARKER_OPEN}${index}-->`;
|
|
703
|
+
}
|
|
704
|
+
function textMarkerCloseStr() {
|
|
705
|
+
return `<!--${TEXT_MARKER_CLOSE}-->`;
|
|
706
|
+
}
|
|
707
|
+
function parseTextOpenMarker(node) {
|
|
708
|
+
const data = node.data;
|
|
709
|
+
if (data.startsWith(TEXT_MARKER_OPEN)) {
|
|
710
|
+
const idx = parseInt(data.slice(TEXT_MARKER_OPEN.length), 10);
|
|
711
|
+
return Number.isNaN(idx) ? -1 : idx;
|
|
712
|
+
}
|
|
713
|
+
return -1;
|
|
714
|
+
}
|
|
715
|
+
function isTextCloseMarker(node) {
|
|
716
|
+
return node.data === TEXT_MARKER_CLOSE;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// src/server/stream.ts
|
|
720
|
+
function createHydratableStreamContext() {
|
|
721
|
+
return { componentIndex: 0, textIndex: 0, eventIndex: 0 };
|
|
722
|
+
}
|
|
723
|
+
var VOID_ELEMENTS3 = new Set([
|
|
724
|
+
"area",
|
|
725
|
+
"base",
|
|
726
|
+
"br",
|
|
727
|
+
"col",
|
|
728
|
+
"embed",
|
|
729
|
+
"hr",
|
|
730
|
+
"img",
|
|
731
|
+
"input",
|
|
732
|
+
"link",
|
|
733
|
+
"meta",
|
|
734
|
+
"param",
|
|
735
|
+
"source",
|
|
736
|
+
"track",
|
|
737
|
+
"wbr"
|
|
738
|
+
]);
|
|
739
|
+
function streamPage(page, data) {
|
|
740
|
+
const encoder = new TextEncoder;
|
|
741
|
+
return new ReadableStream({
|
|
742
|
+
async start(controller) {
|
|
743
|
+
try {
|
|
744
|
+
const element = await page(data);
|
|
745
|
+
await streamNode(element, controller, encoder);
|
|
746
|
+
controller.close();
|
|
747
|
+
} catch (error) {
|
|
748
|
+
controller.error(error);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
function streamHydratablePage(component, props) {
|
|
754
|
+
const encoder = new TextEncoder;
|
|
755
|
+
const ctx = createHydratableStreamContext();
|
|
756
|
+
return new ReadableStream({
|
|
757
|
+
async start(controller) {
|
|
758
|
+
try {
|
|
759
|
+
await streamHydratableComponent(component, props ?? {}, controller, encoder, ctx, true);
|
|
760
|
+
controller.close();
|
|
761
|
+
} catch (error) {
|
|
762
|
+
controller.error(error);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
function streamHydratableNode(node) {
|
|
768
|
+
const encoder = new TextEncoder;
|
|
769
|
+
const ctx = createHydratableStreamContext();
|
|
770
|
+
return new ReadableStream({
|
|
771
|
+
async start(controller) {
|
|
772
|
+
try {
|
|
773
|
+
await streamHydratableNodeToController(node, controller, encoder, ctx);
|
|
774
|
+
controller.close();
|
|
775
|
+
} catch (error) {
|
|
776
|
+
controller.error(error);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
async function streamNode(node, controller, encoder) {
|
|
782
|
+
if (node == null || typeof node === "boolean") {
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
if (typeof node === "string") {
|
|
786
|
+
controller.enqueue(encoder.encode(escapeHtml(node)));
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
if (typeof node === "number") {
|
|
790
|
+
controller.enqueue(encoder.encode(String(node)));
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
if (node instanceof HtmlEscapedString) {
|
|
794
|
+
controller.enqueue(encoder.encode(node.value));
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
if (isSignal(node) || isComputed(node)) {
|
|
798
|
+
controller.enqueue(encoder.encode(escapeHtml(String(node.value))));
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
if (Array.isArray(node)) {
|
|
802
|
+
for (const child of node) {
|
|
803
|
+
await streamNode(child, controller, encoder);
|
|
804
|
+
}
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
if (node instanceof Promise) {
|
|
808
|
+
const resolved = await node;
|
|
809
|
+
await streamElement(resolved, controller, encoder);
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
await streamElement(node, controller, encoder);
|
|
813
|
+
}
|
|
814
|
+
async function streamElement(element, controller, encoder) {
|
|
815
|
+
const { tag, props, children } = element;
|
|
816
|
+
if (isShowElement(element)) {
|
|
817
|
+
const when = readReactive2(props.when);
|
|
818
|
+
await streamNode(when ? resolveShowChildren2(element, when) : props.fallback, controller, encoder);
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
if (isForElement(element)) {
|
|
822
|
+
await streamForElement(element, controller, encoder);
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
if (typeof tag === "function") {
|
|
826
|
+
const result = await tag(props);
|
|
827
|
+
await streamNode(result, controller, encoder);
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
if (typeof tag === "string") {
|
|
831
|
+
await streamIntrinsicElement(tag, props, children, controller, encoder);
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
await streamNode(children, controller, encoder);
|
|
835
|
+
}
|
|
836
|
+
async function streamIntrinsicElement(tag, props, children, controller, encoder) {
|
|
837
|
+
const attrs = renderAttributes2(props);
|
|
838
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
839
|
+
if (VOID_ELEMENTS3.has(tag)) {
|
|
840
|
+
const html = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
841
|
+
controller.enqueue(encoder.encode(html));
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
const openTag = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
845
|
+
controller.enqueue(encoder.encode(openTag));
|
|
846
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
847
|
+
controller.enqueue(encoder.encode(dangerous.__html));
|
|
848
|
+
} else {
|
|
849
|
+
await streamNode(children, controller, encoder);
|
|
850
|
+
}
|
|
851
|
+
controller.enqueue(encoder.encode(`</${tag}>`));
|
|
852
|
+
}
|
|
853
|
+
function renderAttributes2(props) {
|
|
854
|
+
let attrs = "";
|
|
855
|
+
for (const [key, value] of Object.entries(props)) {
|
|
856
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
859
|
+
const resolvedValue = readReactive2(value);
|
|
860
|
+
if (resolvedValue == null || resolvedValue === false)
|
|
861
|
+
continue;
|
|
862
|
+
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
863
|
+
if (resolvedValue === true) {
|
|
864
|
+
attrs += ` ${attrName}`;
|
|
865
|
+
continue;
|
|
866
|
+
}
|
|
867
|
+
const attrValue = escapeHtml(String(resolvedValue));
|
|
868
|
+
attrs += ` ${attrName}="${attrValue}"`;
|
|
869
|
+
}
|
|
870
|
+
return attrs;
|
|
871
|
+
}
|
|
872
|
+
async function streamHydratableNodeToController(node, controller, encoder, ctx, isComponentRoot = false) {
|
|
873
|
+
if (node == null || typeof node === "boolean") {
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
if (typeof node === "string") {
|
|
877
|
+
enqueue(controller, encoder, escapeHtml(node));
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
if (typeof node === "number") {
|
|
881
|
+
enqueue(controller, encoder, String(node));
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
if (node instanceof HtmlEscapedString) {
|
|
885
|
+
enqueue(controller, encoder, node.value);
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
if (isSignal(node) || isComputed(node)) {
|
|
889
|
+
const idx = ctx.textIndex++;
|
|
890
|
+
enqueue(controller, encoder, `${textMarkerOpen(idx)}${escapeHtml(String(node.value))}${textMarkerCloseStr()}`);
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
if (Array.isArray(node)) {
|
|
894
|
+
for (const child of node) {
|
|
895
|
+
await streamHydratableNodeToController(child, controller, encoder, ctx);
|
|
896
|
+
}
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
if (node instanceof Promise) {
|
|
900
|
+
await streamHydratableElement(await node, controller, encoder, ctx, isComponentRoot);
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
await streamHydratableElement(node, controller, encoder, ctx, isComponentRoot);
|
|
904
|
+
}
|
|
905
|
+
async function streamHydratableElement(element, controller, encoder, ctx, isComponentRoot) {
|
|
906
|
+
const { tag, props, children } = element;
|
|
907
|
+
if (tag === "") {
|
|
908
|
+
for (const child of children) {
|
|
909
|
+
await streamHydratableNodeToController(child, controller, encoder, ctx);
|
|
910
|
+
}
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
if (tag === Show || tag === For) {
|
|
914
|
+
await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
if (isShowElement(element)) {
|
|
918
|
+
const when = readReactive2(props.when);
|
|
919
|
+
await streamHydratableNodeToController(when ? resolveShowChildren2(element, when) : props.fallback, controller, encoder, ctx, isComponentRoot);
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
if (isForElement(element)) {
|
|
923
|
+
await streamHydratableForElement(element, controller, encoder, ctx);
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
if (typeof tag === "function") {
|
|
927
|
+
await streamHydratableComponent(tag, props, controller, encoder, ctx, true);
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
if (typeof tag === "string") {
|
|
931
|
+
await streamHydratableIntrinsic(tag, props, children, controller, encoder, ctx, isComponentRoot);
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
await streamHydratableNodeToController(children, controller, encoder, ctx);
|
|
935
|
+
}
|
|
936
|
+
async function streamHydratableComponent(component, props, controller, encoder, ctx, isComponentRoot) {
|
|
937
|
+
const parentInstance = getCurrentInstance();
|
|
938
|
+
const instance = createComponentInstance(component, props, parentInstance);
|
|
939
|
+
if (parentInstance) {
|
|
940
|
+
parentInstance.children.push(instance);
|
|
941
|
+
}
|
|
942
|
+
const prev = setCurrentInstance(instance);
|
|
943
|
+
try {
|
|
944
|
+
const result = await component(props);
|
|
945
|
+
await streamHydratableNodeToController(result, controller, encoder, ctx, isComponentRoot);
|
|
946
|
+
} finally {
|
|
947
|
+
setCurrentInstance(prev);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
async function streamHydratableIntrinsic(tag, props, children, controller, encoder, ctx, isComponentRoot) {
|
|
951
|
+
const attrs = renderHydratableAttributes(props, ctx, isComponentRoot);
|
|
952
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
953
|
+
enqueue(controller, encoder, attrs ? `<${tag}${attrs}>` : `<${tag}>`);
|
|
954
|
+
if (VOID_ELEMENTS3.has(tag)) {
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
958
|
+
enqueue(controller, encoder, dangerous.__html);
|
|
959
|
+
} else {
|
|
960
|
+
for (const child of children) {
|
|
961
|
+
await streamHydratableNodeToController(child, controller, encoder, ctx);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
enqueue(controller, encoder, `</${tag}>`);
|
|
965
|
+
}
|
|
966
|
+
async function streamHydratableForElement(element, controller, encoder, ctx) {
|
|
967
|
+
const props = element.props;
|
|
968
|
+
const each = readReactive2(props.each);
|
|
969
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
for (let index = 0;index < each.length; index++) {
|
|
973
|
+
await streamHydratableNodeToController(props.children(each[index], () => index), controller, encoder, ctx);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
function renderHydratableAttributes(props, ctx, isComponentRoot) {
|
|
977
|
+
let attrs = "";
|
|
978
|
+
if (isComponentRoot) {
|
|
979
|
+
attrs += ` ${COMP_ID_ATTR}="${compId(ctx.componentIndex++)}"`;
|
|
980
|
+
}
|
|
981
|
+
const eventParts = [];
|
|
982
|
+
for (const [key, value] of Object.entries(props)) {
|
|
983
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML") {
|
|
984
|
+
continue;
|
|
985
|
+
}
|
|
986
|
+
if (isEventProp(key)) {
|
|
987
|
+
eventParts.push(`${toEventName(key)}:${ctx.eventIndex++}`);
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
const resolvedValue = readReactive2(value);
|
|
991
|
+
if (resolvedValue == null || resolvedValue === false)
|
|
992
|
+
continue;
|
|
993
|
+
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
994
|
+
if (resolvedValue === true) {
|
|
995
|
+
attrs += ` ${attrName}`;
|
|
996
|
+
continue;
|
|
997
|
+
}
|
|
998
|
+
attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
|
|
999
|
+
}
|
|
1000
|
+
if (eventParts.length > 0) {
|
|
1001
|
+
attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
|
|
1002
|
+
}
|
|
1003
|
+
return attrs;
|
|
1004
|
+
}
|
|
1005
|
+
function enqueue(controller, encoder, html) {
|
|
1006
|
+
controller.enqueue(encoder.encode(html));
|
|
1007
|
+
}
|
|
1008
|
+
async function streamForElement(element, controller, encoder) {
|
|
1009
|
+
const props = element.props;
|
|
1010
|
+
const each = readReactive2(props.each);
|
|
1011
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
for (let index = 0;index < each.length; index++) {
|
|
1015
|
+
await streamNode(props.children(each[index], () => index), controller, encoder);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
function resolveShowChildren2(element, value) {
|
|
1019
|
+
const children = element.props.children ?? element.children;
|
|
1020
|
+
if (typeof children === "function") {
|
|
1021
|
+
return children(value);
|
|
1022
|
+
}
|
|
1023
|
+
return children;
|
|
1024
|
+
}
|
|
1025
|
+
function readReactive2(value) {
|
|
1026
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
1027
|
+
}
|
|
739
1028
|
// src/server/hydration-markers.ts
|
|
740
1029
|
function createHydrationContext() {
|
|
741
1030
|
return { componentIndex: 0, textIndex: 0, eventIndex: 0 };
|
|
@@ -744,13 +1033,16 @@ async function renderToHydratableString(component, props) {
|
|
|
744
1033
|
const ctx = createHydrationContext();
|
|
745
1034
|
const mergedProps = props ?? {};
|
|
746
1035
|
const instance = createComponentInstance(component, mergedProps, null);
|
|
747
|
-
setCurrentInstance(instance);
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1036
|
+
const prev = setCurrentInstance(instance);
|
|
1037
|
+
try {
|
|
1038
|
+
const result = await component(mergedProps);
|
|
1039
|
+
if (result && typeof result === "object" && "tag" in result) {
|
|
1040
|
+
return renderElementH(result, ctx, true);
|
|
1041
|
+
}
|
|
1042
|
+
return renderNodeH(result, ctx);
|
|
1043
|
+
} finally {
|
|
1044
|
+
setCurrentInstance(prev);
|
|
752
1045
|
}
|
|
753
|
-
return renderNodeH(result, ctx);
|
|
754
1046
|
}
|
|
755
1047
|
async function renderNodeToHydratableString(node) {
|
|
756
1048
|
const ctx = createHydrationContext();
|
|
@@ -802,6 +1094,17 @@ function renderElementH(element, ctx, isComponentRoot) {
|
|
|
802
1094
|
if (tag === "") {
|
|
803
1095
|
return children.map((child) => renderNodeH(child, ctx)).join("");
|
|
804
1096
|
}
|
|
1097
|
+
if (tag === Show || tag === For) {
|
|
1098
|
+
return renderElementH(tag(props), ctx, isComponentRoot);
|
|
1099
|
+
}
|
|
1100
|
+
if (isShowElement(element)) {
|
|
1101
|
+
const when = readReactive3(props.when);
|
|
1102
|
+
const content = when ? resolveShowChildren3(element, when) : props.fallback;
|
|
1103
|
+
return renderNodeMaybeRoot(content, ctx, isComponentRoot);
|
|
1104
|
+
}
|
|
1105
|
+
if (isForElement(element)) {
|
|
1106
|
+
return renderForElementH(element, ctx);
|
|
1107
|
+
}
|
|
805
1108
|
if (typeof tag === "function") {
|
|
806
1109
|
return renderComponentH(tag, props, ctx);
|
|
807
1110
|
}
|
|
@@ -811,15 +1114,21 @@ function renderElementH(element, ctx, isComponentRoot) {
|
|
|
811
1114
|
return children.map((child) => renderNodeH(child, ctx)).join("");
|
|
812
1115
|
}
|
|
813
1116
|
function renderComponentH(component, props, ctx) {
|
|
814
|
-
const parentInstance =
|
|
815
|
-
const instance = createComponentInstance(component, props,
|
|
1117
|
+
const parentInstance = getCurrentInstance();
|
|
1118
|
+
const instance = createComponentInstance(component, props, parentInstance);
|
|
1119
|
+
if (parentInstance) {
|
|
1120
|
+
parentInstance.children.push(instance);
|
|
1121
|
+
}
|
|
816
1122
|
const prev = setCurrentInstance(instance);
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
1123
|
+
try {
|
|
1124
|
+
const result = component(props);
|
|
1125
|
+
if (result && typeof result === "object" && "tag" in result) {
|
|
1126
|
+
return renderElementH(result, ctx, true);
|
|
1127
|
+
}
|
|
1128
|
+
return renderNodeH(result, ctx);
|
|
1129
|
+
} finally {
|
|
1130
|
+
setCurrentInstance(prev);
|
|
821
1131
|
}
|
|
822
|
-
return renderNodeH(result, ctx);
|
|
823
1132
|
}
|
|
824
1133
|
function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
|
|
825
1134
|
let attrs = "";
|
|
@@ -828,8 +1137,9 @@ function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
|
|
|
828
1137
|
}
|
|
829
1138
|
const eventParts = [];
|
|
830
1139
|
for (const [key, value] of Object.entries(props)) {
|
|
831
|
-
if (key === "children" || key === "dangerouslySetInnerHTML")
|
|
1140
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML") {
|
|
832
1141
|
continue;
|
|
1142
|
+
}
|
|
833
1143
|
if (isEventProp(key)) {
|
|
834
1144
|
const eventName = toEventName(key);
|
|
835
1145
|
eventParts.push(`${eventName}:${ctx.eventIndex++}`);
|
|
@@ -862,8 +1172,34 @@ function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
|
|
|
862
1172
|
const childrenHtml = children.map((child) => renderNodeH(child, ctx)).join("");
|
|
863
1173
|
return `<${tag}${attrs}>${childrenHtml}</${tag}>`;
|
|
864
1174
|
}
|
|
1175
|
+
function renderNodeMaybeRoot(node, ctx, isComponentRoot) {
|
|
1176
|
+
if (isComponentRoot && node && typeof node === "object" && !Array.isArray(node) && "tag" in node) {
|
|
1177
|
+
return renderElementH(node, ctx, true);
|
|
1178
|
+
}
|
|
1179
|
+
return renderNodeH(node, ctx);
|
|
1180
|
+
}
|
|
1181
|
+
function renderForElementH(element, ctx) {
|
|
1182
|
+
const props = element.props;
|
|
1183
|
+
const each = readReactive3(props.each);
|
|
1184
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1185
|
+
return "";
|
|
1186
|
+
}
|
|
1187
|
+
return each.map((item, index) => renderNodeH(props.children(item, () => index), ctx)).join("");
|
|
1188
|
+
}
|
|
1189
|
+
function resolveShowChildren3(element, value) {
|
|
1190
|
+
const children = element.props.children ?? element.children;
|
|
1191
|
+
if (typeof children === "function") {
|
|
1192
|
+
return children(value);
|
|
1193
|
+
}
|
|
1194
|
+
return children;
|
|
1195
|
+
}
|
|
1196
|
+
function readReactive3(value) {
|
|
1197
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
1198
|
+
}
|
|
865
1199
|
export {
|
|
866
1200
|
streamPage,
|
|
1201
|
+
streamHydratablePage,
|
|
1202
|
+
streamHydratableNode,
|
|
867
1203
|
renderToString,
|
|
868
1204
|
renderToHydratableString,
|
|
869
1205
|
renderPage,
|
|
@@ -874,5 +1210,5 @@ export {
|
|
|
874
1210
|
getPage
|
|
875
1211
|
};
|
|
876
1212
|
|
|
877
|
-
//# debugId=
|
|
1213
|
+
//# debugId=E47F9E2EB5705D1864756E2164756E21
|
|
878
1214
|
//# sourceMappingURL=index.development.js.map
|