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
|
@@ -87,22 +87,12 @@ function buildElement(type, props, children) {
|
|
|
87
87
|
if (type === Fragment) {
|
|
88
88
|
return { tag: "", props: {}, children };
|
|
89
89
|
}
|
|
90
|
-
if (typeof type === "function") {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return result2;
|
|
95
|
-
}
|
|
96
|
-
return { tag: "", props: {}, children: normalizeChildren(result2) };
|
|
97
|
-
}
|
|
98
|
-
const result = type(props);
|
|
99
|
-
if (result && typeof result === "object" && "tag" in result) {
|
|
100
|
-
return result;
|
|
90
|
+
if (typeof type === "function" || typeof type === "string") {
|
|
91
|
+
const finalProps = props ?? {};
|
|
92
|
+
if (children.length > 0 && finalProps.children === undefined) {
|
|
93
|
+
finalProps.children = children.length === 1 ? children[0] : children;
|
|
101
94
|
}
|
|
102
|
-
return { tag:
|
|
103
|
-
}
|
|
104
|
-
if (typeof type === "string") {
|
|
105
|
-
return { tag: type, props: props || {}, children };
|
|
95
|
+
return { tag: type, props: finalProps, children };
|
|
106
96
|
}
|
|
107
97
|
return { tag: "", props: {}, children };
|
|
108
98
|
}
|
|
@@ -122,399 +112,217 @@ function jsxDEV(type, props, key, isStaticChildren, source, self) {
|
|
|
122
112
|
return element;
|
|
123
113
|
}
|
|
124
114
|
|
|
125
|
-
// src/
|
|
126
|
-
var
|
|
127
|
-
__export(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
115
|
+
// src/renderer/index.ts
|
|
116
|
+
var exports_renderer = {};
|
|
117
|
+
__export(exports_renderer, {
|
|
118
|
+
unmountNode: () => unmountNode,
|
|
119
|
+
toEventName: () => toEventName,
|
|
120
|
+
setDOMOps: () => setDOMOps,
|
|
121
|
+
resetDOMOps: () => resetDOMOps,
|
|
122
|
+
renderNodeToDOM: () => renderNodeToDOM,
|
|
123
|
+
renderElementToDOM: () => renderElementToDOM,
|
|
124
|
+
renderChildrenToDOM: () => renderChildrenToDOM,
|
|
125
|
+
render: () => render,
|
|
126
|
+
mount: () => mount,
|
|
127
|
+
isEventProp: () => isEventProp,
|
|
128
|
+
domOps: () => domOps,
|
|
129
|
+
bindEvents: () => bindEvents,
|
|
130
|
+
bindEvent: () => bindEvent,
|
|
131
|
+
applyAttributes: () => applyAttributes
|
|
137
132
|
});
|
|
138
|
-
module.exports = __toCommonJS(
|
|
133
|
+
module.exports = __toCommonJS(exports_renderer);
|
|
139
134
|
|
|
140
|
-
// src/
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
135
|
+
// src/renderer/dom-ops.ts
|
|
136
|
+
function createDefaultDOMOps() {
|
|
137
|
+
return {
|
|
138
|
+
createElement(tag) {
|
|
139
|
+
return document.createElement(tag);
|
|
140
|
+
},
|
|
141
|
+
createElementNS(namespace, tag) {
|
|
142
|
+
return document.createElementNS(namespace, tag);
|
|
143
|
+
},
|
|
144
|
+
createTextNode(text) {
|
|
145
|
+
return document.createTextNode(text);
|
|
146
|
+
},
|
|
147
|
+
createComment(text) {
|
|
148
|
+
return document.createComment(text);
|
|
149
|
+
},
|
|
150
|
+
setAttribute(el, key, value) {
|
|
151
|
+
el.setAttribute(key, value);
|
|
152
|
+
},
|
|
153
|
+
removeAttribute(el, key) {
|
|
154
|
+
el.removeAttribute(key);
|
|
155
|
+
},
|
|
156
|
+
setProperty(el, key, value) {
|
|
157
|
+
el[key] = value;
|
|
158
|
+
},
|
|
159
|
+
insertBefore(parent, child, anchor) {
|
|
160
|
+
parent.insertBefore(child, anchor);
|
|
161
|
+
},
|
|
162
|
+
appendChild(parent, child) {
|
|
163
|
+
parent.appendChild(child);
|
|
164
|
+
},
|
|
165
|
+
remove(node) {
|
|
166
|
+
node.parentNode?.removeChild(node);
|
|
167
|
+
},
|
|
168
|
+
setTextContent(node, text) {
|
|
169
|
+
node.data = text;
|
|
170
|
+
},
|
|
171
|
+
addEventListener(el, event, handler) {
|
|
172
|
+
el.addEventListener(event, handler);
|
|
173
|
+
},
|
|
174
|
+
removeEventListener(el, event, handler) {
|
|
175
|
+
el.removeEventListener(event, handler);
|
|
176
|
+
},
|
|
177
|
+
parentNode(node) {
|
|
178
|
+
return node.parentNode;
|
|
179
|
+
},
|
|
180
|
+
nextSibling(node) {
|
|
181
|
+
return node.nextSibling;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
166
184
|
}
|
|
167
|
-
|
|
168
|
-
|
|
185
|
+
var defaultDOMOps = createDefaultDOMOps();
|
|
186
|
+
var domOps = { ...defaultDOMOps };
|
|
187
|
+
function setDOMOps(overrides) {
|
|
188
|
+
Object.assign(domOps, overrides);
|
|
169
189
|
}
|
|
170
|
-
function
|
|
171
|
-
|
|
190
|
+
function resetDOMOps() {
|
|
191
|
+
for (const key of Object.keys(domOps)) {
|
|
192
|
+
delete domOps[key];
|
|
193
|
+
}
|
|
194
|
+
Object.assign(domOps, defaultDOMOps);
|
|
172
195
|
}
|
|
173
196
|
|
|
174
|
-
// src/
|
|
175
|
-
var
|
|
176
|
-
var
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
197
|
+
// src/reactivity/scheduler.ts
|
|
198
|
+
var pendingEffects = new Set;
|
|
199
|
+
var flushScheduled = false;
|
|
200
|
+
var isFlushing = false;
|
|
201
|
+
var pendingCallbacks = [];
|
|
202
|
+
function scheduleEffect(effect) {
|
|
203
|
+
if (!effect.active)
|
|
204
|
+
return;
|
|
205
|
+
pendingEffects.add(effect);
|
|
206
|
+
scheduleFlush();
|
|
182
207
|
}
|
|
183
|
-
function
|
|
184
|
-
|
|
208
|
+
function unscheduleEffect(effect) {
|
|
209
|
+
pendingEffects.delete(effect);
|
|
185
210
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
211
|
+
function scheduleFlush() {
|
|
212
|
+
if (!flushScheduled) {
|
|
213
|
+
flushScheduled = true;
|
|
214
|
+
queueMicrotask(flush);
|
|
190
215
|
}
|
|
191
|
-
const element = await page(data);
|
|
192
|
-
return renderToString(element);
|
|
193
216
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
return String(node);
|
|
203
|
-
}
|
|
204
|
-
if (node instanceof HtmlEscapedString) {
|
|
205
|
-
return node.value;
|
|
217
|
+
function flush() {
|
|
218
|
+
isFlushing = true;
|
|
219
|
+
const sorted = [...pendingEffects].sort((a, b) => a.id - b.id);
|
|
220
|
+
pendingEffects.clear();
|
|
221
|
+
for (const effect of sorted) {
|
|
222
|
+
if (effect.active) {
|
|
223
|
+
effect.run();
|
|
224
|
+
}
|
|
206
225
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
226
|
+
let safety = 10;
|
|
227
|
+
while (pendingEffects.size > 0 && safety-- > 0) {
|
|
228
|
+
const next = [...pendingEffects].sort((a, b) => a.id - b.id);
|
|
229
|
+
pendingEffects.clear();
|
|
230
|
+
for (const effect of next) {
|
|
231
|
+
if (effect.active) {
|
|
232
|
+
effect.run();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
210
235
|
}
|
|
211
|
-
|
|
212
|
-
|
|
236
|
+
flushScheduled = false;
|
|
237
|
+
isFlushing = false;
|
|
238
|
+
const cbs = pendingCallbacks.splice(0);
|
|
239
|
+
for (const cb of cbs) {
|
|
240
|
+
cb();
|
|
213
241
|
}
|
|
214
|
-
return renderElement(node);
|
|
215
242
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
243
|
+
function nextTick(fn) {
|
|
244
|
+
return new Promise((resolve) => {
|
|
245
|
+
const callback = () => {
|
|
246
|
+
fn?.();
|
|
247
|
+
resolve();
|
|
248
|
+
};
|
|
249
|
+
if (flushScheduled || isFlushing) {
|
|
250
|
+
pendingCallbacks.push(callback);
|
|
251
|
+
} else {
|
|
252
|
+
queueMicrotask(callback);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
226
255
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
"col",
|
|
232
|
-
"embed",
|
|
233
|
-
"hr",
|
|
234
|
-
"img",
|
|
235
|
-
"input",
|
|
236
|
-
"link",
|
|
237
|
-
"meta",
|
|
238
|
-
"param",
|
|
239
|
-
"source",
|
|
240
|
-
"track",
|
|
241
|
-
"wbr"
|
|
242
|
-
]);
|
|
243
|
-
async function renderIntrinsicElement(tag, props, children) {
|
|
244
|
-
const attrs = renderAttributes(props);
|
|
245
|
-
if (VOID_ELEMENTS2.has(tag)) {
|
|
246
|
-
return attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
256
|
+
function flushSync() {
|
|
257
|
+
if (flushScheduled) {
|
|
258
|
+
flushScheduled = false;
|
|
259
|
+
flush();
|
|
247
260
|
}
|
|
248
|
-
const childrenHtml = await renderChildren(children, props);
|
|
249
|
-
return attrs ? `<${tag}${attrs}>${childrenHtml}</${tag}>` : `<${tag}>${childrenHtml}</${tag}>`;
|
|
250
261
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
262
|
+
|
|
263
|
+
// src/reactivity/effect.ts
|
|
264
|
+
var activeEffect = null;
|
|
265
|
+
var effectStack = [];
|
|
266
|
+
var effectIdCounter = 0;
|
|
267
|
+
|
|
268
|
+
class ReactiveEffect {
|
|
269
|
+
id;
|
|
270
|
+
active = true;
|
|
271
|
+
fn;
|
|
272
|
+
cleanup = undefined;
|
|
273
|
+
deps = new Set;
|
|
274
|
+
constructor(fn) {
|
|
275
|
+
this.id = effectIdCounter++;
|
|
276
|
+
this.fn = fn;
|
|
277
|
+
}
|
|
278
|
+
run() {
|
|
279
|
+
if (!this.active)
|
|
280
|
+
return;
|
|
281
|
+
if (effectStack.includes(this))
|
|
282
|
+
return;
|
|
283
|
+
this.cleanupDeps();
|
|
284
|
+
if (this.cleanup) {
|
|
285
|
+
this.cleanup();
|
|
286
|
+
this.cleanup = undefined;
|
|
261
287
|
}
|
|
262
|
-
|
|
263
|
-
|
|
288
|
+
effectStack.push(this);
|
|
289
|
+
const prevEffect = activeEffect;
|
|
290
|
+
activeEffect = this;
|
|
291
|
+
try {
|
|
292
|
+
const result = this.fn();
|
|
293
|
+
if (typeof result === "function") {
|
|
294
|
+
this.cleanup = result;
|
|
295
|
+
}
|
|
296
|
+
} finally {
|
|
297
|
+
activeEffect = prevEffect;
|
|
298
|
+
effectStack.pop();
|
|
264
299
|
}
|
|
265
|
-
const attrName = key === "className" ? "class" : key;
|
|
266
|
-
const finalName = attrName === "htmlFor" ? "for" : attrName;
|
|
267
|
-
const attrValue = escapeHtml(String(value));
|
|
268
|
-
attrs += ` ${finalName}="${attrValue}"`;
|
|
269
300
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
301
|
+
cleanupDeps() {
|
|
302
|
+
for (const dep of this.deps) {
|
|
303
|
+
dep.subscribers.delete(this);
|
|
304
|
+
}
|
|
305
|
+
this.deps.clear();
|
|
306
|
+
}
|
|
307
|
+
notify() {
|
|
308
|
+
scheduleEffect(this);
|
|
309
|
+
}
|
|
310
|
+
dispose() {
|
|
311
|
+
if (!this.active)
|
|
312
|
+
return;
|
|
313
|
+
this.active = false;
|
|
314
|
+
if (this.cleanup) {
|
|
315
|
+
this.cleanup();
|
|
316
|
+
this.cleanup = undefined;
|
|
317
|
+
}
|
|
318
|
+
this.cleanupDeps();
|
|
319
|
+
unscheduleEffect(this);
|
|
276
320
|
}
|
|
277
|
-
return renderToString(children);
|
|
278
321
|
}
|
|
279
|
-
function
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
var VOID_ELEMENTS3 = new Set([
|
|
284
|
-
"area",
|
|
285
|
-
"base",
|
|
286
|
-
"br",
|
|
287
|
-
"col",
|
|
288
|
-
"embed",
|
|
289
|
-
"hr",
|
|
290
|
-
"img",
|
|
291
|
-
"input",
|
|
292
|
-
"link",
|
|
293
|
-
"meta",
|
|
294
|
-
"param",
|
|
295
|
-
"source",
|
|
296
|
-
"track",
|
|
297
|
-
"wbr"
|
|
298
|
-
]);
|
|
299
|
-
function streamPage(page, data) {
|
|
300
|
-
const encoder = new TextEncoder;
|
|
301
|
-
return new ReadableStream({
|
|
302
|
-
async start(controller) {
|
|
303
|
-
try {
|
|
304
|
-
const element = await page(data);
|
|
305
|
-
await streamNode(element, controller, encoder);
|
|
306
|
-
controller.close();
|
|
307
|
-
} catch (error) {
|
|
308
|
-
controller.error(error);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
async function streamNode(node, controller, encoder) {
|
|
314
|
-
if (node == null || typeof node === "boolean") {
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
if (typeof node === "string") {
|
|
318
|
-
controller.enqueue(encoder.encode(escapeHtml(node)));
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
if (typeof node === "number") {
|
|
322
|
-
controller.enqueue(encoder.encode(String(node)));
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
if (node instanceof HtmlEscapedString) {
|
|
326
|
-
controller.enqueue(encoder.encode(node.value));
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
if (Array.isArray(node)) {
|
|
330
|
-
for (const child of node) {
|
|
331
|
-
await streamNode(child, controller, encoder);
|
|
332
|
-
}
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
if (node instanceof Promise) {
|
|
336
|
-
const resolved = await node;
|
|
337
|
-
await streamElement(resolved, controller, encoder);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
await streamElement(node, controller, encoder);
|
|
341
|
-
}
|
|
342
|
-
async function streamElement(element, controller, encoder) {
|
|
343
|
-
const { tag, props, children } = element;
|
|
344
|
-
if (typeof tag === "function") {
|
|
345
|
-
const result = await tag(props);
|
|
346
|
-
await streamNode(result, controller, encoder);
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
if (typeof tag === "string") {
|
|
350
|
-
await streamIntrinsicElement(tag, props, children, controller, encoder);
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
await streamNode(children, controller, encoder);
|
|
354
|
-
}
|
|
355
|
-
async function streamIntrinsicElement(tag, props, children, controller, encoder) {
|
|
356
|
-
const attrs = renderAttributes2(props);
|
|
357
|
-
const dangerous = props.dangerouslySetInnerHTML;
|
|
358
|
-
if (VOID_ELEMENTS3.has(tag)) {
|
|
359
|
-
const html = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
360
|
-
controller.enqueue(encoder.encode(html));
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
const openTag = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
364
|
-
controller.enqueue(encoder.encode(openTag));
|
|
365
|
-
if (dangerous && typeof dangerous.__html === "string") {
|
|
366
|
-
controller.enqueue(encoder.encode(dangerous.__html));
|
|
367
|
-
} else {
|
|
368
|
-
await streamNode(children, controller, encoder);
|
|
369
|
-
}
|
|
370
|
-
controller.enqueue(encoder.encode(`</${tag}>`));
|
|
371
|
-
}
|
|
372
|
-
function renderAttributes2(props) {
|
|
373
|
-
let attrs = "";
|
|
374
|
-
for (const [key, value] of Object.entries(props)) {
|
|
375
|
-
if (key === "children" || key === "dangerouslySetInnerHTML")
|
|
376
|
-
continue;
|
|
377
|
-
if (value == null || value === false)
|
|
378
|
-
continue;
|
|
379
|
-
if (value === true) {
|
|
380
|
-
attrs += ` ${key}`;
|
|
381
|
-
continue;
|
|
382
|
-
}
|
|
383
|
-
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
384
|
-
const attrValue = escapeHtml(String(value));
|
|
385
|
-
attrs += ` ${attrName}="${attrValue}"`;
|
|
386
|
-
}
|
|
387
|
-
return attrs;
|
|
388
|
-
}
|
|
389
|
-
// src/reactivity/scheduler.ts
|
|
390
|
-
var pendingEffects = new Set;
|
|
391
|
-
var flushScheduled = false;
|
|
392
|
-
var isFlushing = false;
|
|
393
|
-
var pendingCallbacks = [];
|
|
394
|
-
function scheduleEffect(effect) {
|
|
395
|
-
if (!effect.active)
|
|
396
|
-
return;
|
|
397
|
-
pendingEffects.add(effect);
|
|
398
|
-
scheduleFlush();
|
|
399
|
-
}
|
|
400
|
-
function unscheduleEffect(effect) {
|
|
401
|
-
pendingEffects.delete(effect);
|
|
402
|
-
}
|
|
403
|
-
function scheduleFlush() {
|
|
404
|
-
if (!flushScheduled) {
|
|
405
|
-
flushScheduled = true;
|
|
406
|
-
queueMicrotask(flush);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
function flush() {
|
|
410
|
-
isFlushing = true;
|
|
411
|
-
const sorted = [...pendingEffects].sort((a, b) => a.id - b.id);
|
|
412
|
-
pendingEffects.clear();
|
|
413
|
-
for (const effect of sorted) {
|
|
414
|
-
if (effect.active) {
|
|
415
|
-
effect.run();
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
let safety = 10;
|
|
419
|
-
while (pendingEffects.size > 0 && safety-- > 0) {
|
|
420
|
-
const next = [...pendingEffects].sort((a, b) => a.id - b.id);
|
|
421
|
-
pendingEffects.clear();
|
|
422
|
-
for (const effect of next) {
|
|
423
|
-
if (effect.active) {
|
|
424
|
-
effect.run();
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
flushScheduled = false;
|
|
429
|
-
isFlushing = false;
|
|
430
|
-
const cbs = pendingCallbacks.splice(0);
|
|
431
|
-
for (const cb of cbs) {
|
|
432
|
-
cb();
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
function nextTick(fn) {
|
|
436
|
-
return new Promise((resolve) => {
|
|
437
|
-
const callback = () => {
|
|
438
|
-
fn?.();
|
|
439
|
-
resolve();
|
|
440
|
-
};
|
|
441
|
-
if (flushScheduled || isFlushing) {
|
|
442
|
-
pendingCallbacks.push(callback);
|
|
443
|
-
} else {
|
|
444
|
-
queueMicrotask(callback);
|
|
445
|
-
}
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
function flushSync() {
|
|
449
|
-
if (flushScheduled) {
|
|
450
|
-
flushScheduled = false;
|
|
451
|
-
flush();
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// src/reactivity/effect.ts
|
|
456
|
-
var activeEffect = null;
|
|
457
|
-
var effectStack = [];
|
|
458
|
-
var effectIdCounter = 0;
|
|
459
|
-
|
|
460
|
-
class ReactiveEffect {
|
|
461
|
-
id;
|
|
462
|
-
active = true;
|
|
463
|
-
fn;
|
|
464
|
-
cleanup = undefined;
|
|
465
|
-
deps = new Set;
|
|
466
|
-
constructor(fn) {
|
|
467
|
-
this.id = effectIdCounter++;
|
|
468
|
-
this.fn = fn;
|
|
469
|
-
}
|
|
470
|
-
run() {
|
|
471
|
-
if (!this.active)
|
|
472
|
-
return;
|
|
473
|
-
if (effectStack.includes(this))
|
|
474
|
-
return;
|
|
475
|
-
this.cleanupDeps();
|
|
476
|
-
if (this.cleanup) {
|
|
477
|
-
this.cleanup();
|
|
478
|
-
this.cleanup = undefined;
|
|
479
|
-
}
|
|
480
|
-
effectStack.push(this);
|
|
481
|
-
const prevEffect = activeEffect;
|
|
482
|
-
activeEffect = this;
|
|
483
|
-
try {
|
|
484
|
-
const result = this.fn();
|
|
485
|
-
if (typeof result === "function") {
|
|
486
|
-
this.cleanup = result;
|
|
487
|
-
}
|
|
488
|
-
} finally {
|
|
489
|
-
activeEffect = prevEffect;
|
|
490
|
-
effectStack.pop();
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
cleanupDeps() {
|
|
494
|
-
for (const dep of this.deps) {
|
|
495
|
-
dep.subscribers.delete(this);
|
|
496
|
-
}
|
|
497
|
-
this.deps.clear();
|
|
498
|
-
}
|
|
499
|
-
notify() {
|
|
500
|
-
scheduleEffect(this);
|
|
501
|
-
}
|
|
502
|
-
dispose() {
|
|
503
|
-
if (!this.active)
|
|
504
|
-
return;
|
|
505
|
-
this.active = false;
|
|
506
|
-
if (this.cleanup) {
|
|
507
|
-
this.cleanup();
|
|
508
|
-
this.cleanup = undefined;
|
|
509
|
-
}
|
|
510
|
-
this.cleanupDeps();
|
|
511
|
-
unscheduleEffect(this);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
function effect(fn) {
|
|
515
|
-
const e = new ReactiveEffect(fn);
|
|
516
|
-
e.run();
|
|
517
|
-
return () => e.dispose();
|
|
322
|
+
function effect(fn) {
|
|
323
|
+
const e = new ReactiveEffect(fn);
|
|
324
|
+
e.run();
|
|
325
|
+
return () => e.dispose();
|
|
518
326
|
}
|
|
519
327
|
function track(dep) {
|
|
520
328
|
if (activeEffect) {
|
|
@@ -628,91 +436,18 @@ function isComputed(value) {
|
|
|
628
436
|
return value != null && typeof value === "object" && COMPUTED_BRAND in value;
|
|
629
437
|
}
|
|
630
438
|
|
|
631
|
-
// src/
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
var TEXT_MARKER_OPEN = "sinwan-t:";
|
|
635
|
-
var TEXT_MARKER_CLOSE = "/sinwan-t";
|
|
636
|
-
var EVENT_ATTR = "data-sinwan-ev";
|
|
637
|
-
function compId(index) {
|
|
638
|
-
return `${COMP_ID_PREFIX}${index}`;
|
|
439
|
+
// src/renderer/events.ts
|
|
440
|
+
function isEventProp(key) {
|
|
441
|
+
return key.length > 2 && key[0] === "o" && key[1] === "n" && key[2] >= "A" && key[2] <= "Z";
|
|
639
442
|
}
|
|
640
|
-
function
|
|
641
|
-
return
|
|
443
|
+
function toEventName(key) {
|
|
444
|
+
return key.slice(2).toLowerCase();
|
|
642
445
|
}
|
|
643
|
-
function
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
if (data.startsWith(TEXT_MARKER_OPEN)) {
|
|
649
|
-
const idx = parseInt(data.slice(TEXT_MARKER_OPEN.length), 10);
|
|
650
|
-
return Number.isNaN(idx) ? -1 : idx;
|
|
651
|
-
}
|
|
652
|
-
return -1;
|
|
653
|
-
}
|
|
654
|
-
function isTextCloseMarker(node) {
|
|
655
|
-
return node.data === TEXT_MARKER_CLOSE;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
// src/renderer/dom-ops.ts
|
|
659
|
-
var domOps = {
|
|
660
|
-
createElement(tag) {
|
|
661
|
-
return document.createElement(tag);
|
|
662
|
-
},
|
|
663
|
-
createTextNode(text) {
|
|
664
|
-
return document.createTextNode(text);
|
|
665
|
-
},
|
|
666
|
-
createComment(text) {
|
|
667
|
-
return document.createComment(text);
|
|
668
|
-
},
|
|
669
|
-
setAttribute(el, key, value) {
|
|
670
|
-
el.setAttribute(key, value);
|
|
671
|
-
},
|
|
672
|
-
removeAttribute(el, key) {
|
|
673
|
-
el.removeAttribute(key);
|
|
674
|
-
},
|
|
675
|
-
setProperty(el, key, value) {
|
|
676
|
-
el[key] = value;
|
|
677
|
-
},
|
|
678
|
-
insertBefore(parent, child, anchor) {
|
|
679
|
-
parent.insertBefore(child, anchor);
|
|
680
|
-
},
|
|
681
|
-
appendChild(parent, child) {
|
|
682
|
-
parent.appendChild(child);
|
|
683
|
-
},
|
|
684
|
-
remove(node) {
|
|
685
|
-
node.parentNode?.removeChild(node);
|
|
686
|
-
},
|
|
687
|
-
setTextContent(node, text) {
|
|
688
|
-
node.data = text;
|
|
689
|
-
},
|
|
690
|
-
addEventListener(el, event, handler) {
|
|
691
|
-
el.addEventListener(event, handler);
|
|
692
|
-
},
|
|
693
|
-
removeEventListener(el, event, handler) {
|
|
694
|
-
el.removeEventListener(event, handler);
|
|
695
|
-
},
|
|
696
|
-
parentNode(node) {
|
|
697
|
-
return node.parentNode;
|
|
698
|
-
},
|
|
699
|
-
nextSibling(node) {
|
|
700
|
-
return node.nextSibling;
|
|
701
|
-
}
|
|
702
|
-
};
|
|
703
|
-
|
|
704
|
-
// src/renderer/events.ts
|
|
705
|
-
function isEventProp(key) {
|
|
706
|
-
return key.length > 2 && key[0] === "o" && key[1] === "n" && key[2] >= "A" && key[2] <= "Z";
|
|
707
|
-
}
|
|
708
|
-
function toEventName(key) {
|
|
709
|
-
return key.slice(2).toLowerCase();
|
|
710
|
-
}
|
|
711
|
-
function bindEvent(el, eventName, handler) {
|
|
712
|
-
domOps.addEventListener(el, eventName, handler);
|
|
713
|
-
return () => {
|
|
714
|
-
domOps.removeEventListener(el, eventName, handler);
|
|
715
|
-
};
|
|
446
|
+
function bindEvent(el, eventName, handler) {
|
|
447
|
+
domOps.addEventListener(el, eventName, handler);
|
|
448
|
+
return () => {
|
|
449
|
+
domOps.removeEventListener(el, eventName, handler);
|
|
450
|
+
};
|
|
716
451
|
}
|
|
717
452
|
function bindEvents(el, props) {
|
|
718
453
|
const cleanups = [];
|
|
@@ -757,7 +492,18 @@ function setCurrentInstance(instance) {
|
|
|
757
492
|
currentInstance = instance;
|
|
758
493
|
return prev;
|
|
759
494
|
}
|
|
495
|
+
function withInstance(instance, fn) {
|
|
496
|
+
const prev = setCurrentInstance(instance);
|
|
497
|
+
try {
|
|
498
|
+
return fn();
|
|
499
|
+
} finally {
|
|
500
|
+
setCurrentInstance(prev);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
760
503
|
function fireMountedHooks(instance) {
|
|
504
|
+
if (instance.isUnmounted) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
761
507
|
for (const child of instance.children) {
|
|
762
508
|
fireMountedHooks(child);
|
|
763
509
|
}
|
|
@@ -784,6 +530,24 @@ function fireUnmountedHooks(instance) {
|
|
|
784
530
|
instance.effects.length = 0;
|
|
785
531
|
}
|
|
786
532
|
}
|
|
533
|
+
function fireUpdatedHooks(instance) {
|
|
534
|
+
for (const hook of instance._updatedHooks) {
|
|
535
|
+
hook();
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
var queuedUpdatedHooks = new Set;
|
|
539
|
+
function queueUpdatedHooks(instance) {
|
|
540
|
+
if (!instance || !instance.isMounted || instance.isUnmounted || instance._updatedHooks.length === 0 || queuedUpdatedHooks.has(instance)) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
queuedUpdatedHooks.add(instance);
|
|
544
|
+
nextTick(() => {
|
|
545
|
+
queuedUpdatedHooks.delete(instance);
|
|
546
|
+
if (instance.isMounted && !instance.isUnmounted) {
|
|
547
|
+
fireUpdatedHooks(instance);
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
}
|
|
787
551
|
function handleComponentError(instance, err) {
|
|
788
552
|
let current = instance;
|
|
789
553
|
while (current) {
|
|
@@ -798,27 +562,327 @@ function handleComponentError(instance, err) {
|
|
|
798
562
|
console.error("[Sinwan] Unhandled component error:", err);
|
|
799
563
|
}
|
|
800
564
|
|
|
801
|
-
// src/
|
|
802
|
-
|
|
803
|
-
|
|
565
|
+
// src/renderer/attributes.ts
|
|
566
|
+
var SKIP_PROPS = new Set(["children", "key", "ref", "dangerouslySetInnerHTML"]);
|
|
567
|
+
var DOM_PROPERTIES = new Set(["value", "checked", "selected", "disabled", "readOnly", "multiple", "indeterminate"]);
|
|
568
|
+
var PROP_ALIASES = {
|
|
569
|
+
className: "class",
|
|
570
|
+
htmlFor: "for",
|
|
571
|
+
tabIndex: "tabindex",
|
|
572
|
+
crossOrigin: "crossorigin"
|
|
573
|
+
};
|
|
574
|
+
function applyAttributes(el, props) {
|
|
575
|
+
const disposers = [];
|
|
576
|
+
const owner = getCurrentInstance();
|
|
577
|
+
for (const [key, value] of Object.entries(props)) {
|
|
578
|
+
if (SKIP_PROPS.has(key) || isEventProp(key))
|
|
579
|
+
continue;
|
|
580
|
+
if (isSignal(value) || isComputed(value)) {
|
|
581
|
+
let initialized = false;
|
|
582
|
+
const dispose = effect(() => {
|
|
583
|
+
setSingleAttribute(el, key, value.value);
|
|
584
|
+
if (initialized) {
|
|
585
|
+
queueUpdatedHooks(owner);
|
|
586
|
+
}
|
|
587
|
+
initialized = true;
|
|
588
|
+
});
|
|
589
|
+
disposers.push(dispose);
|
|
590
|
+
} else {
|
|
591
|
+
setSingleAttribute(el, key, value);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return disposers;
|
|
804
595
|
}
|
|
805
|
-
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
return
|
|
596
|
+
function setSingleAttribute(el, key, value) {
|
|
597
|
+
const attrName = PROP_ALIASES[key] ?? key;
|
|
598
|
+
if (attrName === "style" && typeof value === "object" && value !== null) {
|
|
599
|
+
applyStyle(el, value);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
if (attrName === "class" && typeof value === "object" && value !== null) {
|
|
603
|
+
applyClass(el, value);
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
if (value == null || value === false) {
|
|
607
|
+
domOps.removeAttribute(el, attrName);
|
|
608
|
+
if (DOM_PROPERTIES.has(attrName)) {
|
|
609
|
+
domOps.setProperty(el, attrName, attrName === "value" ? "" : false);
|
|
610
|
+
}
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (value === true) {
|
|
614
|
+
domOps.setAttribute(el, attrName, "");
|
|
615
|
+
if (DOM_PROPERTIES.has(attrName)) {
|
|
616
|
+
domOps.setProperty(el, attrName, true);
|
|
617
|
+
}
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
if (DOM_PROPERTIES.has(attrName)) {
|
|
621
|
+
domOps.setProperty(el, attrName, value);
|
|
622
|
+
return;
|
|
814
623
|
}
|
|
815
|
-
|
|
624
|
+
domOps.setAttribute(el, attrName, String(value));
|
|
816
625
|
}
|
|
817
|
-
|
|
818
|
-
const
|
|
819
|
-
|
|
626
|
+
function applyStyle(el, styles) {
|
|
627
|
+
for (const [prop, val] of Object.entries(styles)) {
|
|
628
|
+
if (prop.includes("-")) {
|
|
629
|
+
el.style.setProperty(prop, val);
|
|
630
|
+
} else {
|
|
631
|
+
el.style[prop] = val;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
820
634
|
}
|
|
821
|
-
|
|
635
|
+
function applyClass(el, value) {
|
|
636
|
+
let classStr;
|
|
637
|
+
if (Array.isArray(value)) {
|
|
638
|
+
classStr = value.filter(Boolean).join(" ");
|
|
639
|
+
} else if (typeof value === "object" && value !== null) {
|
|
640
|
+
classStr = Object.entries(value).filter(([, v]) => Boolean(v)).map(([k]) => k).join(" ");
|
|
641
|
+
} else {
|
|
642
|
+
classStr = String(value);
|
|
643
|
+
}
|
|
644
|
+
domOps.setAttribute(el, "class", classStr);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// src/component/control-flow.ts
|
|
648
|
+
var SHOW_TYPE = Symbol.for("Sinwan.Show");
|
|
649
|
+
var FOR_TYPE = Symbol.for("Sinwan.For");
|
|
650
|
+
function Show(props) {
|
|
651
|
+
return {
|
|
652
|
+
tag: SHOW_TYPE,
|
|
653
|
+
props,
|
|
654
|
+
children: []
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
function For(props) {
|
|
658
|
+
return {
|
|
659
|
+
tag: FOR_TYPE,
|
|
660
|
+
props,
|
|
661
|
+
children: []
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
function isShowElement(element) {
|
|
665
|
+
return element.tag === SHOW_TYPE;
|
|
666
|
+
}
|
|
667
|
+
function isForElement(element) {
|
|
668
|
+
return element.tag === FOR_TYPE;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// src/renderer/unmount.ts
|
|
672
|
+
function getMountedDomNodes(node) {
|
|
673
|
+
switch (node.type) {
|
|
674
|
+
case "text":
|
|
675
|
+
case "reactive-text":
|
|
676
|
+
return [node.node];
|
|
677
|
+
case "element":
|
|
678
|
+
return [node.node];
|
|
679
|
+
case "fragment":
|
|
680
|
+
return [
|
|
681
|
+
node.anchor,
|
|
682
|
+
...node.children.flatMap((child) => getMountedDomNodes(child))
|
|
683
|
+
];
|
|
684
|
+
case "reactive-block":
|
|
685
|
+
return [
|
|
686
|
+
node.startAnchor,
|
|
687
|
+
...node.children.flatMap((child) => getMountedDomNodes(child)),
|
|
688
|
+
node.endAnchor
|
|
689
|
+
];
|
|
690
|
+
case "component":
|
|
691
|
+
return node.children.flatMap((child) => getMountedDomNodes(child));
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
function unmountNode(node) {
|
|
695
|
+
switch (node.type) {
|
|
696
|
+
case "text":
|
|
697
|
+
break;
|
|
698
|
+
case "reactive-text":
|
|
699
|
+
node.dispose();
|
|
700
|
+
break;
|
|
701
|
+
case "element":
|
|
702
|
+
for (const dispose of node.attrDisposers) {
|
|
703
|
+
dispose();
|
|
704
|
+
}
|
|
705
|
+
for (const cleanup of node.eventCleanups) {
|
|
706
|
+
cleanup();
|
|
707
|
+
}
|
|
708
|
+
node.refCleanup?.();
|
|
709
|
+
for (const child of node.children) {
|
|
710
|
+
unmountNode(child);
|
|
711
|
+
}
|
|
712
|
+
break;
|
|
713
|
+
case "fragment":
|
|
714
|
+
for (const child of node.children) {
|
|
715
|
+
unmountNode(child);
|
|
716
|
+
}
|
|
717
|
+
break;
|
|
718
|
+
case "reactive-block":
|
|
719
|
+
node.dispose();
|
|
720
|
+
for (const child of node.children) {
|
|
721
|
+
unmountNode(child);
|
|
722
|
+
}
|
|
723
|
+
break;
|
|
724
|
+
case "component":
|
|
725
|
+
if (node.instance) {
|
|
726
|
+
fireUnmountedHooks(node.instance);
|
|
727
|
+
} else {
|
|
728
|
+
for (const dispose of node.disposers) {
|
|
729
|
+
dispose();
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
for (const child of node.children) {
|
|
733
|
+
unmountNode(child);
|
|
734
|
+
}
|
|
735
|
+
break;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
function removeMountedNode(node) {
|
|
739
|
+
const domNodes = getMountedDomNodes(node);
|
|
740
|
+
unmountNode(node);
|
|
741
|
+
for (const domNode of domNodes) {
|
|
742
|
+
if (domNode.parentNode) {
|
|
743
|
+
domOps.remove(domNode);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// src/renderer/render-control-flow.ts
|
|
749
|
+
function renderControlFlowToDOM(element, parent, anchor, namespace) {
|
|
750
|
+
const startAnchor = domOps.createComment("Sinwan-b");
|
|
751
|
+
const endAnchor = domOps.createComment("/Sinwan-b");
|
|
752
|
+
insertNode(parent, startAnchor, anchor);
|
|
753
|
+
insertNode(parent, endAnchor, anchor);
|
|
754
|
+
const owner = getCurrentInstance();
|
|
755
|
+
let disposeEffect = () => {};
|
|
756
|
+
const block = {
|
|
757
|
+
type: "reactive-block",
|
|
758
|
+
dispose: () => disposeEffect(),
|
|
759
|
+
children: [],
|
|
760
|
+
startAnchor,
|
|
761
|
+
endAnchor
|
|
762
|
+
};
|
|
763
|
+
if (isShowElement(element)) {
|
|
764
|
+
disposeEffect = renderShowBlock(element, block, parent, namespace, owner);
|
|
765
|
+
} else if (isForElement(element)) {
|
|
766
|
+
disposeEffect = renderForBlock(element, block, parent, namespace, owner);
|
|
767
|
+
}
|
|
768
|
+
return block;
|
|
769
|
+
}
|
|
770
|
+
function renderShowBlock(element, block, parent, namespace, owner) {
|
|
771
|
+
let initialized = false;
|
|
772
|
+
return effect(() => {
|
|
773
|
+
clearChildren(block);
|
|
774
|
+
const when = readReactive(element.props.when);
|
|
775
|
+
const content = withOptionalInstance(owner, () => when ? resolveShowChildren(element, when) : element.props.fallback);
|
|
776
|
+
block.children = renderBlockContent(content, parent, block.endAnchor, namespace, owner);
|
|
777
|
+
if (initialized) {
|
|
778
|
+
fireMountedAndQueueUpdated(owner);
|
|
779
|
+
}
|
|
780
|
+
initialized = true;
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
function renderForBlock(element, block, parent, namespace, owner) {
|
|
784
|
+
let initialized = false;
|
|
785
|
+
let records = [];
|
|
786
|
+
return effect(() => {
|
|
787
|
+
const props = element.props;
|
|
788
|
+
const items = readReactive(props.each);
|
|
789
|
+
const list = Array.isArray(items) ? items : [];
|
|
790
|
+
const renderChild = props.children;
|
|
791
|
+
if (typeof renderChild !== "function") {
|
|
792
|
+
clearChildren(block);
|
|
793
|
+
records = [];
|
|
794
|
+
if (initialized) {
|
|
795
|
+
queueUpdatedHooks(owner);
|
|
796
|
+
}
|
|
797
|
+
initialized = true;
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
const oldByKey = new Map;
|
|
801
|
+
for (const record of records) {
|
|
802
|
+
oldByKey.set(record.key, record);
|
|
803
|
+
}
|
|
804
|
+
const nextRecords = [];
|
|
805
|
+
list.forEach((item, index) => {
|
|
806
|
+
const key = props.key ? props.key(item, index) : item;
|
|
807
|
+
const old = oldByKey.get(key);
|
|
808
|
+
if (old && old.item === item) {
|
|
809
|
+
old.index = index;
|
|
810
|
+
moveBeforeEnd(parent, old.mounted, block.endAnchor);
|
|
811
|
+
nextRecords.push(old);
|
|
812
|
+
oldByKey.delete(key);
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
if (old) {
|
|
816
|
+
removeMountedNode(old.mounted);
|
|
817
|
+
oldByKey.delete(key);
|
|
818
|
+
}
|
|
819
|
+
const record = {
|
|
820
|
+
key,
|
|
821
|
+
item,
|
|
822
|
+
index,
|
|
823
|
+
mounted: { type: "text", node: domOps.createTextNode("") }
|
|
824
|
+
};
|
|
825
|
+
record.mounted = withOptionalInstance(owner, () => renderNodeToDOM(renderChild(item, () => record.index), parent, block.endAnchor, namespace));
|
|
826
|
+
nextRecords.push(record);
|
|
827
|
+
});
|
|
828
|
+
for (const record of oldByKey.values()) {
|
|
829
|
+
removeMountedNode(record.mounted);
|
|
830
|
+
}
|
|
831
|
+
records = nextRecords;
|
|
832
|
+
block.children = nextRecords.map((record) => record.mounted);
|
|
833
|
+
if (initialized) {
|
|
834
|
+
fireMountedAndQueueUpdated(owner);
|
|
835
|
+
}
|
|
836
|
+
initialized = true;
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
function resolveShowChildren(element, value) {
|
|
840
|
+
const children = element.props.children ?? element.children;
|
|
841
|
+
if (typeof children === "function") {
|
|
842
|
+
return children(value);
|
|
843
|
+
}
|
|
844
|
+
return children;
|
|
845
|
+
}
|
|
846
|
+
function renderBlockContent(content, parent, anchor, namespace, owner) {
|
|
847
|
+
if (content == null || typeof content === "boolean") {
|
|
848
|
+
return [];
|
|
849
|
+
}
|
|
850
|
+
const nodes = Array.isArray(content) ? content : [content];
|
|
851
|
+
return nodes.map((node) => withOptionalInstance(owner, () => renderNodeToDOM(node, parent, anchor, namespace)));
|
|
852
|
+
}
|
|
853
|
+
function clearChildren(block) {
|
|
854
|
+
for (const child of block.children) {
|
|
855
|
+
removeMountedNode(child);
|
|
856
|
+
}
|
|
857
|
+
block.children = [];
|
|
858
|
+
}
|
|
859
|
+
function moveBeforeEnd(parent, mounted, endAnchor) {
|
|
860
|
+
for (const node of getMountedDomNodes(mounted)) {
|
|
861
|
+
domOps.insertBefore(parent, node, endAnchor);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
function fireMountedAndQueueUpdated(owner) {
|
|
865
|
+
if (owner) {
|
|
866
|
+
fireMountedHooks(owner);
|
|
867
|
+
}
|
|
868
|
+
queueUpdatedHooks(owner);
|
|
869
|
+
}
|
|
870
|
+
function withOptionalInstance(owner, fn) {
|
|
871
|
+
return owner ? withInstance(owner, fn) : fn();
|
|
872
|
+
}
|
|
873
|
+
function readReactive(value) {
|
|
874
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
875
|
+
}
|
|
876
|
+
function insertNode(parent, child, anchor) {
|
|
877
|
+
if (anchor) {
|
|
878
|
+
domOps.insertBefore(parent, child, anchor);
|
|
879
|
+
} else {
|
|
880
|
+
domOps.appendChild(parent, child);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// src/renderer/render-element.ts
|
|
885
|
+
var VOID_ELEMENTS2 = new Set([
|
|
822
886
|
"area",
|
|
823
887
|
"base",
|
|
824
888
|
"br",
|
|
@@ -834,298 +898,824 @@ var VOID_ELEMENTS4 = new Set([
|
|
|
834
898
|
"track",
|
|
835
899
|
"wbr"
|
|
836
900
|
]);
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
return String(node);
|
|
844
|
-
if (node instanceof HtmlEscapedString)
|
|
845
|
-
return node.value;
|
|
846
|
-
if (isSignal(node) || isComputed(node)) {
|
|
847
|
-
const value = node.value;
|
|
848
|
-
const idx = ctx.textIndex++;
|
|
849
|
-
return `${textMarkerOpen(idx)}${escapeHtml(String(value))}${textMarkerCloseStr()}`;
|
|
901
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
902
|
+
var MATH_NS = "http://www.w3.org/1998/Math/MathML";
|
|
903
|
+
function renderElementToDOM(element, parent, anchor = null, namespace = null) {
|
|
904
|
+
const { tag, props, children } = element;
|
|
905
|
+
if (tag === "" || tag === Fragment) {
|
|
906
|
+
return renderFragmentToDOM(children, parent, anchor, namespace);
|
|
850
907
|
}
|
|
851
|
-
if (
|
|
852
|
-
return
|
|
908
|
+
if (tag === Show || tag === For) {
|
|
909
|
+
return renderElementToDOM(tag(props), parent, anchor, namespace);
|
|
853
910
|
}
|
|
854
|
-
if (
|
|
855
|
-
return
|
|
911
|
+
if (isShowElement(element) || isForElement(element)) {
|
|
912
|
+
return renderControlFlowToDOM(element, parent, anchor, namespace);
|
|
856
913
|
}
|
|
857
|
-
if (typeof
|
|
858
|
-
return
|
|
914
|
+
if (typeof tag === "function") {
|
|
915
|
+
return renderComponentToDOM(tag, props, parent, anchor, namespace);
|
|
859
916
|
}
|
|
860
|
-
|
|
917
|
+
if (typeof tag === "string") {
|
|
918
|
+
return renderIntrinsicToDOM(tag, props, children, parent, anchor, namespace);
|
|
919
|
+
}
|
|
920
|
+
return renderFragmentToDOM(children, parent, anchor, namespace);
|
|
921
|
+
}
|
|
922
|
+
function renderIntrinsicToDOM(tag, props, children, parent, anchor, parentNamespace) {
|
|
923
|
+
const namespace = getElementNamespace(tag, parentNamespace);
|
|
924
|
+
const el = namespace ? domOps.createElementNS(namespace, tag) : domOps.createElement(tag);
|
|
925
|
+
const attrDisposers = applyAttributes(el, props);
|
|
926
|
+
const eventCleanups = bindEvents(el, props);
|
|
927
|
+
let mountedChildren = [];
|
|
928
|
+
if (!VOID_ELEMENTS2.has(tag)) {
|
|
929
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
930
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
931
|
+
el.innerHTML = dangerous.__html;
|
|
932
|
+
} else {
|
|
933
|
+
mountedChildren = renderChildrenToDOM(children, el, getChildNamespace(tag, namespace));
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
if (anchor) {
|
|
937
|
+
domOps.insertBefore(parent, el, anchor);
|
|
938
|
+
} else {
|
|
939
|
+
domOps.appendChild(parent, el);
|
|
940
|
+
}
|
|
941
|
+
const refCleanup = applyRef(el, props.ref);
|
|
942
|
+
return {
|
|
943
|
+
type: "element",
|
|
944
|
+
node: el,
|
|
945
|
+
children: mountedChildren,
|
|
946
|
+
eventCleanups,
|
|
947
|
+
attrDisposers,
|
|
948
|
+
refCleanup
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
function renderComponentToDOM(component, props, parent, anchor, namespace) {
|
|
952
|
+
const parentInstance = getCurrentInstance();
|
|
953
|
+
const instance = createComponentInstance(component, props, parentInstance);
|
|
954
|
+
if (parentInstance) {
|
|
955
|
+
parentInstance.children.push(instance);
|
|
956
|
+
}
|
|
957
|
+
const prevInstance = setCurrentInstance(instance);
|
|
958
|
+
let result;
|
|
959
|
+
let child;
|
|
960
|
+
try {
|
|
961
|
+
result = component(props);
|
|
962
|
+
if (result && typeof result === "object" && "tag" in result) {
|
|
963
|
+
child = renderElementToDOM(result, parent, anchor, namespace);
|
|
964
|
+
} else {
|
|
965
|
+
child = renderNodeToDOM(result, parent, anchor, namespace);
|
|
966
|
+
}
|
|
967
|
+
} catch (err) {
|
|
968
|
+
setCurrentInstance(prevInstance);
|
|
969
|
+
handleComponentError(instance, err);
|
|
970
|
+
const text = domOps.createTextNode("");
|
|
971
|
+
if (anchor) {
|
|
972
|
+
domOps.insertBefore(parent, text, anchor);
|
|
973
|
+
} else {
|
|
974
|
+
domOps.appendChild(parent, text);
|
|
975
|
+
}
|
|
976
|
+
return {
|
|
977
|
+
type: "component",
|
|
978
|
+
children: [{ type: "text", node: text }],
|
|
979
|
+
disposers: [],
|
|
980
|
+
instance
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
setCurrentInstance(prevInstance);
|
|
984
|
+
instance.element = child;
|
|
985
|
+
return {
|
|
986
|
+
type: "component",
|
|
987
|
+
children: [child],
|
|
988
|
+
disposers: instance.effects,
|
|
989
|
+
instance
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
function renderFragmentToDOM(children, parent, anchor, namespace) {
|
|
993
|
+
const anchorComment = domOps.createComment("Sinwan-f");
|
|
994
|
+
if (anchor) {
|
|
995
|
+
domOps.insertBefore(parent, anchorComment, anchor);
|
|
996
|
+
} else {
|
|
997
|
+
domOps.appendChild(parent, anchorComment);
|
|
998
|
+
}
|
|
999
|
+
const mounted = [];
|
|
1000
|
+
for (const child of children) {
|
|
1001
|
+
mounted.push(renderNodeToDOM(child, parent, anchor, namespace));
|
|
1002
|
+
}
|
|
1003
|
+
return { type: "fragment", children: mounted, anchor: anchorComment };
|
|
1004
|
+
}
|
|
1005
|
+
function getElementNamespace(tag, parentNamespace) {
|
|
1006
|
+
if (tag === "svg")
|
|
1007
|
+
return SVG_NS;
|
|
1008
|
+
if (tag === "math")
|
|
1009
|
+
return MATH_NS;
|
|
1010
|
+
return parentNamespace;
|
|
1011
|
+
}
|
|
1012
|
+
function getChildNamespace(tag, namespace) {
|
|
1013
|
+
if (namespace === SVG_NS && tag === "foreignObject") {
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
return namespace;
|
|
1017
|
+
}
|
|
1018
|
+
function applyRef(el, ref) {
|
|
1019
|
+
const value = ref;
|
|
1020
|
+
if (!value) {
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
1023
|
+
if (typeof value === "function") {
|
|
1024
|
+
value(el);
|
|
1025
|
+
return () => value(null);
|
|
1026
|
+
}
|
|
1027
|
+
if (typeof value === "object" && "current" in value) {
|
|
1028
|
+
value.current = el;
|
|
1029
|
+
return () => {
|
|
1030
|
+
value.current = null;
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
return null;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// src/renderer/render-children.ts
|
|
1037
|
+
function renderNodeToDOM(node, parent, anchor = null, namespace = null) {
|
|
1038
|
+
if (node == null || typeof node === "boolean") {
|
|
1039
|
+
const text2 = domOps.createTextNode("");
|
|
1040
|
+
insertNode2(parent, text2, anchor);
|
|
1041
|
+
return { type: "text", node: text2 };
|
|
1042
|
+
}
|
|
1043
|
+
if (typeof node === "string") {
|
|
1044
|
+
const text2 = domOps.createTextNode(node);
|
|
1045
|
+
insertNode2(parent, text2, anchor);
|
|
1046
|
+
return { type: "text", node: text2 };
|
|
1047
|
+
}
|
|
1048
|
+
if (typeof node === "number") {
|
|
1049
|
+
const text2 = domOps.createTextNode(String(node));
|
|
1050
|
+
insertNode2(parent, text2, anchor);
|
|
1051
|
+
return { type: "text", node: text2 };
|
|
1052
|
+
}
|
|
1053
|
+
if (node instanceof HtmlEscapedString) {
|
|
1054
|
+
const text2 = domOps.createTextNode(node.value);
|
|
1055
|
+
insertNode2(parent, text2, anchor);
|
|
1056
|
+
return { type: "text", node: text2 };
|
|
1057
|
+
}
|
|
1058
|
+
if (isSignal(node) || isComputed(node)) {
|
|
1059
|
+
const text2 = domOps.createTextNode(String(node.value));
|
|
1060
|
+
insertNode2(parent, text2, anchor);
|
|
1061
|
+
const owner = getCurrentInstance();
|
|
1062
|
+
let initialized = false;
|
|
1063
|
+
const dispose = effect(() => {
|
|
1064
|
+
domOps.setTextContent(text2, String(node.value));
|
|
1065
|
+
if (initialized) {
|
|
1066
|
+
queueUpdatedHooks(owner);
|
|
1067
|
+
}
|
|
1068
|
+
initialized = true;
|
|
1069
|
+
});
|
|
1070
|
+
return { type: "reactive-text", node: text2, dispose };
|
|
1071
|
+
}
|
|
1072
|
+
if (Array.isArray(node)) {
|
|
1073
|
+
return renderArrayToDOM(node, parent, anchor, namespace);
|
|
1074
|
+
}
|
|
1075
|
+
if (node instanceof Promise) {
|
|
1076
|
+
const placeholder = domOps.createTextNode("");
|
|
1077
|
+
insertNode2(parent, placeholder, anchor);
|
|
1078
|
+
node.then((resolved) => {
|
|
1079
|
+
const mounted = renderNodeToDOM(resolved, parent, placeholder, namespace);
|
|
1080
|
+
domOps.remove(placeholder);
|
|
1081
|
+
});
|
|
1082
|
+
return { type: "text", node: placeholder };
|
|
1083
|
+
}
|
|
1084
|
+
if (typeof node === "object" && "tag" in node) {
|
|
1085
|
+
return renderElementToDOM(node, parent, anchor, namespace);
|
|
1086
|
+
}
|
|
1087
|
+
const text = domOps.createTextNode(String(node));
|
|
1088
|
+
insertNode2(parent, text, anchor);
|
|
1089
|
+
return { type: "text", node: text };
|
|
1090
|
+
}
|
|
1091
|
+
function renderArrayToDOM(nodes, parent, anchor, namespace) {
|
|
1092
|
+
const anchorComment = domOps.createComment("Sinwan-f");
|
|
1093
|
+
insertNode2(parent, anchorComment, anchor);
|
|
1094
|
+
const children = [];
|
|
1095
|
+
for (const child of nodes) {
|
|
1096
|
+
children.push(renderNodeToDOM(child, parent, anchor, namespace));
|
|
1097
|
+
}
|
|
1098
|
+
return { type: "fragment", children, anchor: anchorComment };
|
|
1099
|
+
}
|
|
1100
|
+
function renderChildrenToDOM(children, parent, namespace = null) {
|
|
1101
|
+
const mounted = [];
|
|
1102
|
+
for (const child of children) {
|
|
1103
|
+
mounted.push(renderNodeToDOM(child, parent, null, namespace));
|
|
1104
|
+
}
|
|
1105
|
+
return mounted;
|
|
1106
|
+
}
|
|
1107
|
+
function insertNode2(parent, child, anchor) {
|
|
1108
|
+
if (anchor) {
|
|
1109
|
+
domOps.insertBefore(parent, child, anchor);
|
|
1110
|
+
} else {
|
|
1111
|
+
domOps.appendChild(parent, child);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// src/renderer/mount.ts
|
|
1116
|
+
function mount(component, container, props) {
|
|
1117
|
+
container.innerHTML = "";
|
|
1118
|
+
const mergedProps = props ?? {};
|
|
1119
|
+
const instance = createComponentInstance(component, mergedProps, null);
|
|
1120
|
+
let result;
|
|
1121
|
+
let root;
|
|
1122
|
+
setCurrentInstance(instance);
|
|
1123
|
+
try {
|
|
1124
|
+
result = component(mergedProps);
|
|
1125
|
+
if (result instanceof Promise) {
|
|
1126
|
+
const placeholder = document.createTextNode("");
|
|
1127
|
+
container.appendChild(placeholder);
|
|
1128
|
+
root = { type: "text", node: placeholder };
|
|
1129
|
+
result.then((resolved) => {
|
|
1130
|
+
container.innerHTML = "";
|
|
1131
|
+
setCurrentInstance(instance);
|
|
1132
|
+
root = renderElementToDOM(resolved, container);
|
|
1133
|
+
setCurrentInstance(null);
|
|
1134
|
+
instance.element = root;
|
|
1135
|
+
fireMountedHooks(instance);
|
|
1136
|
+
});
|
|
1137
|
+
} else if (result && typeof result === "object" && "tag" in result) {
|
|
1138
|
+
root = renderElementToDOM(result, container);
|
|
1139
|
+
} else {
|
|
1140
|
+
root = renderNodeToDOM(result, container);
|
|
1141
|
+
}
|
|
1142
|
+
} catch (err) {
|
|
1143
|
+
setCurrentInstance(null);
|
|
1144
|
+
handleComponentError(instance, err);
|
|
1145
|
+
return {
|
|
1146
|
+
root: { type: "text", node: document.createTextNode("") },
|
|
1147
|
+
unmount() {}
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
setCurrentInstance(null);
|
|
1151
|
+
instance.element = root;
|
|
1152
|
+
fireMountedHooks(instance);
|
|
1153
|
+
return {
|
|
1154
|
+
root,
|
|
1155
|
+
unmount() {
|
|
1156
|
+
fireUnmountedHooks(instance);
|
|
1157
|
+
unmountNode(root);
|
|
1158
|
+
container.innerHTML = "";
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
function render(node, container) {
|
|
1163
|
+
container.innerHTML = "";
|
|
1164
|
+
const root = renderNodeToDOM(node, container);
|
|
1165
|
+
return {
|
|
1166
|
+
root,
|
|
1167
|
+
unmount() {
|
|
1168
|
+
unmountNode(root);
|
|
1169
|
+
container.innerHTML = "";
|
|
1170
|
+
}
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
// src/server/index.ts
|
|
1174
|
+
var exports_server = {};
|
|
1175
|
+
__export(exports_server, {
|
|
1176
|
+
streamPage: () => streamPage,
|
|
1177
|
+
streamHydratablePage: () => streamHydratablePage,
|
|
1178
|
+
streamHydratableNode: () => streamHydratableNode,
|
|
1179
|
+
renderToString: () => renderToString,
|
|
1180
|
+
renderToHydratableString: () => renderToHydratableString,
|
|
1181
|
+
renderPage: () => renderPage,
|
|
1182
|
+
renderNodeToHydratableString: () => renderNodeToHydratableString,
|
|
1183
|
+
registerPage: () => registerPage,
|
|
1184
|
+
isSlots: () => isSlots,
|
|
1185
|
+
hasPage: () => hasPage,
|
|
1186
|
+
getPage: () => getPage
|
|
1187
|
+
});
|
|
1188
|
+
module.exports = __toCommonJS(exports_server);
|
|
1189
|
+
|
|
1190
|
+
// src/escaper.ts
|
|
1191
|
+
var _bun = globalThis.Bun;
|
|
1192
|
+
var _nativeEscape = typeof _bun?.escapeHTML === "function" ? _bun.escapeHTML.bind(_bun) : undefined;
|
|
1193
|
+
var HTML_ESCAPE_RE = /[&<>"']/g;
|
|
1194
|
+
var HTML_ESCAPE_MAP = {
|
|
1195
|
+
"&": "&",
|
|
1196
|
+
"<": "<",
|
|
1197
|
+
">": ">",
|
|
1198
|
+
'"': """,
|
|
1199
|
+
"'": "'"
|
|
1200
|
+
};
|
|
1201
|
+
function portableEscape(str) {
|
|
1202
|
+
HTML_ESCAPE_RE.lastIndex = 0;
|
|
1203
|
+
if (!HTML_ESCAPE_RE.test(str))
|
|
1204
|
+
return str;
|
|
1205
|
+
return str.replace(HTML_ESCAPE_RE, (c) => HTML_ESCAPE_MAP[c]);
|
|
1206
|
+
}
|
|
1207
|
+
function escapeHtml(value) {
|
|
1208
|
+
if (value == null || typeof value === "boolean")
|
|
1209
|
+
return "";
|
|
1210
|
+
if (typeof value === "number")
|
|
1211
|
+
return String(value);
|
|
1212
|
+
if (value instanceof HtmlEscapedString)
|
|
1213
|
+
return value.value;
|
|
1214
|
+
const s = String(value);
|
|
1215
|
+
return _nativeEscape ? _nativeEscape(s) : portableEscape(s);
|
|
1216
|
+
}
|
|
1217
|
+
function safeHtml(html) {
|
|
1218
|
+
return raw(html);
|
|
1219
|
+
}
|
|
1220
|
+
function isSafeHtml(value) {
|
|
1221
|
+
return value instanceof HtmlEscapedString;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
// src/server/renderer.ts
|
|
1225
|
+
var componentCache = new WeakMap;
|
|
1226
|
+
var pageRegistry = new Map;
|
|
1227
|
+
function registerPage(name, page) {
|
|
1228
|
+
pageRegistry.set(name, page);
|
|
1229
|
+
}
|
|
1230
|
+
function getPage(name) {
|
|
1231
|
+
return pageRegistry.get(name);
|
|
1232
|
+
}
|
|
1233
|
+
function hasPage(name) {
|
|
1234
|
+
return pageRegistry.has(name);
|
|
1235
|
+
}
|
|
1236
|
+
async function renderPage(name, data) {
|
|
1237
|
+
const page = getPage(name);
|
|
1238
|
+
if (!page) {
|
|
1239
|
+
throw new Error(`Page "${name}" not found in registry`);
|
|
1240
|
+
}
|
|
1241
|
+
const element = await page(data);
|
|
1242
|
+
return renderToString(element);
|
|
1243
|
+
}
|
|
1244
|
+
async function renderToString(node) {
|
|
1245
|
+
if (node == null || typeof node === "boolean") {
|
|
1246
|
+
return "";
|
|
1247
|
+
}
|
|
1248
|
+
if (typeof node === "string") {
|
|
1249
|
+
return escapeHtml(node);
|
|
1250
|
+
}
|
|
1251
|
+
if (typeof node === "number") {
|
|
1252
|
+
return String(node);
|
|
1253
|
+
}
|
|
1254
|
+
if (node instanceof HtmlEscapedString) {
|
|
1255
|
+
return node.value;
|
|
1256
|
+
}
|
|
1257
|
+
if (isSignal(node) || isComputed(node)) {
|
|
1258
|
+
return escapeHtml(String(node.value));
|
|
1259
|
+
}
|
|
1260
|
+
if (Array.isArray(node)) {
|
|
1261
|
+
const results = await Promise.all(node.map((child) => renderToString(child)));
|
|
1262
|
+
return results.join("");
|
|
1263
|
+
}
|
|
1264
|
+
if (node instanceof Promise) {
|
|
1265
|
+
return renderElement(await node);
|
|
1266
|
+
}
|
|
1267
|
+
return renderElement(node);
|
|
1268
|
+
}
|
|
1269
|
+
async function renderElement(element) {
|
|
1270
|
+
const { tag, props, children } = element;
|
|
1271
|
+
if (isShowElement(element)) {
|
|
1272
|
+
const when = readReactive2(props.when);
|
|
1273
|
+
return renderToString(when ? resolveShowChildren2(element, when) : props.fallback);
|
|
1274
|
+
}
|
|
1275
|
+
if (isForElement(element)) {
|
|
1276
|
+
return renderForElement(element);
|
|
1277
|
+
}
|
|
1278
|
+
if (typeof tag === "function") {
|
|
1279
|
+
const result = await tag(props);
|
|
1280
|
+
return renderToString(result);
|
|
1281
|
+
}
|
|
1282
|
+
if (typeof tag === "string") {
|
|
1283
|
+
return renderIntrinsicElement(tag, props, children);
|
|
1284
|
+
}
|
|
1285
|
+
return renderToString(children);
|
|
1286
|
+
}
|
|
1287
|
+
var VOID_ELEMENTS3 = new Set([
|
|
1288
|
+
"area",
|
|
1289
|
+
"base",
|
|
1290
|
+
"br",
|
|
1291
|
+
"col",
|
|
1292
|
+
"embed",
|
|
1293
|
+
"hr",
|
|
1294
|
+
"img",
|
|
1295
|
+
"input",
|
|
1296
|
+
"link",
|
|
1297
|
+
"meta",
|
|
1298
|
+
"param",
|
|
1299
|
+
"source",
|
|
1300
|
+
"track",
|
|
1301
|
+
"wbr"
|
|
1302
|
+
]);
|
|
1303
|
+
async function renderIntrinsicElement(tag, props, children) {
|
|
1304
|
+
const attrs = renderAttributes(props);
|
|
1305
|
+
if (VOID_ELEMENTS3.has(tag)) {
|
|
1306
|
+
return attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
1307
|
+
}
|
|
1308
|
+
const childrenHtml = await renderChildren(children, props);
|
|
1309
|
+
return attrs ? `<${tag}${attrs}>${childrenHtml}</${tag}>` : `<${tag}>${childrenHtml}</${tag}>`;
|
|
1310
|
+
}
|
|
1311
|
+
function renderAttributes(props) {
|
|
1312
|
+
let attrs = "";
|
|
1313
|
+
for (const [key, value] of Object.entries(props)) {
|
|
1314
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
|
|
1315
|
+
continue;
|
|
1316
|
+
}
|
|
1317
|
+
const resolvedValue = readReactive2(value);
|
|
1318
|
+
if (resolvedValue == null || resolvedValue === false)
|
|
1319
|
+
continue;
|
|
1320
|
+
const attrName = key === "className" ? "class" : key;
|
|
1321
|
+
const finalName = attrName === "htmlFor" ? "for" : attrName;
|
|
1322
|
+
if (resolvedValue === true) {
|
|
1323
|
+
attrs += ` ${finalName}`;
|
|
1324
|
+
continue;
|
|
1325
|
+
}
|
|
1326
|
+
const attrValue = escapeHtml(String(resolvedValue));
|
|
1327
|
+
attrs += ` ${finalName}="${attrValue}"`;
|
|
1328
|
+
}
|
|
1329
|
+
return attrs;
|
|
1330
|
+
}
|
|
1331
|
+
async function renderChildren(children, props) {
|
|
1332
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
1333
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
1334
|
+
return dangerous.__html;
|
|
1335
|
+
}
|
|
1336
|
+
return renderToString(children);
|
|
1337
|
+
}
|
|
1338
|
+
function isSlots(children) {
|
|
1339
|
+
return children != null && typeof children === "object" && !Array.isArray(children) && !(children instanceof HtmlEscapedString);
|
|
1340
|
+
}
|
|
1341
|
+
async function renderForElement(element) {
|
|
1342
|
+
const props = element.props;
|
|
1343
|
+
const each = readReactive2(props.each);
|
|
1344
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1345
|
+
return "";
|
|
1346
|
+
}
|
|
1347
|
+
const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(item, () => index))));
|
|
1348
|
+
return rendered.join("");
|
|
1349
|
+
}
|
|
1350
|
+
function resolveShowChildren2(element, value) {
|
|
1351
|
+
const children = element.props.children ?? element.children;
|
|
1352
|
+
if (typeof children === "function") {
|
|
1353
|
+
return children(value);
|
|
1354
|
+
}
|
|
1355
|
+
return children;
|
|
1356
|
+
}
|
|
1357
|
+
function readReactive2(value) {
|
|
1358
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
1359
|
+
}
|
|
1360
|
+
// src/hydration/markers.ts
|
|
1361
|
+
var COMP_ID_ATTR = "data-sinwan-id";
|
|
1362
|
+
var COMP_ID_PREFIX = "c";
|
|
1363
|
+
var TEXT_MARKER_OPEN = "sinwan-t:";
|
|
1364
|
+
var TEXT_MARKER_CLOSE = "/sinwan-t";
|
|
1365
|
+
var EVENT_ATTR = "data-sinwan-ev";
|
|
1366
|
+
function compId(index) {
|
|
1367
|
+
return `${COMP_ID_PREFIX}${index}`;
|
|
1368
|
+
}
|
|
1369
|
+
function textMarkerOpen(index) {
|
|
1370
|
+
return `<!--${TEXT_MARKER_OPEN}${index}-->`;
|
|
1371
|
+
}
|
|
1372
|
+
function textMarkerCloseStr() {
|
|
1373
|
+
return `<!--${TEXT_MARKER_CLOSE}-->`;
|
|
1374
|
+
}
|
|
1375
|
+
function parseTextOpenMarker(node) {
|
|
1376
|
+
const data = node.data;
|
|
1377
|
+
if (data.startsWith(TEXT_MARKER_OPEN)) {
|
|
1378
|
+
const idx = parseInt(data.slice(TEXT_MARKER_OPEN.length), 10);
|
|
1379
|
+
return Number.isNaN(idx) ? -1 : idx;
|
|
1380
|
+
}
|
|
1381
|
+
return -1;
|
|
1382
|
+
}
|
|
1383
|
+
function isTextCloseMarker(node) {
|
|
1384
|
+
return node.data === TEXT_MARKER_CLOSE;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
// src/server/stream.ts
|
|
1388
|
+
function createHydratableStreamContext() {
|
|
1389
|
+
return { componentIndex: 0, textIndex: 0, eventIndex: 0 };
|
|
1390
|
+
}
|
|
1391
|
+
var VOID_ELEMENTS4 = new Set([
|
|
1392
|
+
"area",
|
|
1393
|
+
"base",
|
|
1394
|
+
"br",
|
|
1395
|
+
"col",
|
|
1396
|
+
"embed",
|
|
1397
|
+
"hr",
|
|
1398
|
+
"img",
|
|
1399
|
+
"input",
|
|
1400
|
+
"link",
|
|
1401
|
+
"meta",
|
|
1402
|
+
"param",
|
|
1403
|
+
"source",
|
|
1404
|
+
"track",
|
|
1405
|
+
"wbr"
|
|
1406
|
+
]);
|
|
1407
|
+
function streamPage(page, data) {
|
|
1408
|
+
const encoder = new TextEncoder;
|
|
1409
|
+
return new ReadableStream({
|
|
1410
|
+
async start(controller) {
|
|
1411
|
+
try {
|
|
1412
|
+
const element = await page(data);
|
|
1413
|
+
await streamNode(element, controller, encoder);
|
|
1414
|
+
controller.close();
|
|
1415
|
+
} catch (error) {
|
|
1416
|
+
controller.error(error);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
function streamHydratablePage(component, props) {
|
|
1422
|
+
const encoder = new TextEncoder;
|
|
1423
|
+
const ctx = createHydratableStreamContext();
|
|
1424
|
+
return new ReadableStream({
|
|
1425
|
+
async start(controller) {
|
|
1426
|
+
try {
|
|
1427
|
+
await streamHydratableComponent(component, props ?? {}, controller, encoder, ctx, true);
|
|
1428
|
+
controller.close();
|
|
1429
|
+
} catch (error) {
|
|
1430
|
+
controller.error(error);
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
function streamHydratableNode(node) {
|
|
1436
|
+
const encoder = new TextEncoder;
|
|
1437
|
+
const ctx = createHydratableStreamContext();
|
|
1438
|
+
return new ReadableStream({
|
|
1439
|
+
async start(controller) {
|
|
1440
|
+
try {
|
|
1441
|
+
await streamHydratableNodeToController(node, controller, encoder, ctx);
|
|
1442
|
+
controller.close();
|
|
1443
|
+
} catch (error) {
|
|
1444
|
+
controller.error(error);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
861
1448
|
}
|
|
862
|
-
function
|
|
1449
|
+
async function streamNode(node, controller, encoder) {
|
|
1450
|
+
if (node == null || typeof node === "boolean") {
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
if (typeof node === "string") {
|
|
1454
|
+
controller.enqueue(encoder.encode(escapeHtml(node)));
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
if (typeof node === "number") {
|
|
1458
|
+
controller.enqueue(encoder.encode(String(node)));
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
if (node instanceof HtmlEscapedString) {
|
|
1462
|
+
controller.enqueue(encoder.encode(node.value));
|
|
1463
|
+
return;
|
|
1464
|
+
}
|
|
1465
|
+
if (isSignal(node) || isComputed(node)) {
|
|
1466
|
+
controller.enqueue(encoder.encode(escapeHtml(String(node.value))));
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1469
|
+
if (Array.isArray(node)) {
|
|
1470
|
+
for (const child of node) {
|
|
1471
|
+
await streamNode(child, controller, encoder);
|
|
1472
|
+
}
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1475
|
+
if (node instanceof Promise) {
|
|
1476
|
+
const resolved = await node;
|
|
1477
|
+
await streamElement(resolved, controller, encoder);
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
await streamElement(node, controller, encoder);
|
|
1481
|
+
}
|
|
1482
|
+
async function streamElement(element, controller, encoder) {
|
|
863
1483
|
const { tag, props, children } = element;
|
|
864
|
-
if (
|
|
865
|
-
|
|
1484
|
+
if (isShowElement(element)) {
|
|
1485
|
+
const when = readReactive3(props.when);
|
|
1486
|
+
await streamNode(when ? resolveShowChildren3(element, when) : props.fallback, controller, encoder);
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
if (isForElement(element)) {
|
|
1490
|
+
await streamForElement(element, controller, encoder);
|
|
1491
|
+
return;
|
|
866
1492
|
}
|
|
867
1493
|
if (typeof tag === "function") {
|
|
868
|
-
|
|
1494
|
+
const result = await tag(props);
|
|
1495
|
+
await streamNode(result, controller, encoder);
|
|
1496
|
+
return;
|
|
869
1497
|
}
|
|
870
1498
|
if (typeof tag === "string") {
|
|
871
|
-
|
|
1499
|
+
await streamIntrinsicElement(tag, props, children, controller, encoder);
|
|
1500
|
+
return;
|
|
872
1501
|
}
|
|
873
|
-
|
|
1502
|
+
await streamNode(children, controller, encoder);
|
|
874
1503
|
}
|
|
875
|
-
function
|
|
876
|
-
const
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
1504
|
+
async function streamIntrinsicElement(tag, props, children, controller, encoder) {
|
|
1505
|
+
const attrs = renderAttributes2(props);
|
|
1506
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
1507
|
+
if (VOID_ELEMENTS4.has(tag)) {
|
|
1508
|
+
const html = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
1509
|
+
controller.enqueue(encoder.encode(html));
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
1512
|
+
const openTag = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
1513
|
+
controller.enqueue(encoder.encode(openTag));
|
|
1514
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
1515
|
+
controller.enqueue(encoder.encode(dangerous.__html));
|
|
1516
|
+
} else {
|
|
1517
|
+
await streamNode(children, controller, encoder);
|
|
883
1518
|
}
|
|
884
|
-
|
|
1519
|
+
controller.enqueue(encoder.encode(`</${tag}>`));
|
|
885
1520
|
}
|
|
886
|
-
function
|
|
1521
|
+
function renderAttributes2(props) {
|
|
887
1522
|
let attrs = "";
|
|
888
|
-
if (isComponentRoot) {
|
|
889
|
-
attrs += ` ${COMP_ID_ATTR}="${compId(ctx.componentIndex++)}"`;
|
|
890
|
-
}
|
|
891
|
-
const eventParts = [];
|
|
892
1523
|
for (const [key, value] of Object.entries(props)) {
|
|
893
|
-
if (key === "children" || key === "dangerouslySetInnerHTML")
|
|
894
|
-
continue;
|
|
895
|
-
if (isEventProp(key)) {
|
|
896
|
-
const eventName = toEventName(key);
|
|
897
|
-
eventParts.push(`${eventName}:${ctx.eventIndex++}`);
|
|
1524
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
|
|
898
1525
|
continue;
|
|
899
1526
|
}
|
|
900
|
-
|
|
1527
|
+
const resolvedValue = readReactive3(value);
|
|
1528
|
+
if (resolvedValue == null || resolvedValue === false)
|
|
901
1529
|
continue;
|
|
902
|
-
|
|
903
|
-
if (isSignal(value) || isComputed(value)) {
|
|
904
|
-
resolvedValue = value.value;
|
|
905
|
-
}
|
|
1530
|
+
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
906
1531
|
if (resolvedValue === true) {
|
|
907
|
-
|
|
908
|
-
attrs += ` ${attrName2}`;
|
|
1532
|
+
attrs += ` ${attrName}`;
|
|
909
1533
|
continue;
|
|
910
1534
|
}
|
|
911
|
-
const
|
|
912
|
-
attrs += ` ${attrName}="${
|
|
913
|
-
}
|
|
914
|
-
if (eventParts.length > 0) {
|
|
915
|
-
attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
|
|
1535
|
+
const attrValue = escapeHtml(String(resolvedValue));
|
|
1536
|
+
attrs += ` ${attrName}="${attrValue}"`;
|
|
916
1537
|
}
|
|
917
|
-
|
|
918
|
-
|
|
1538
|
+
return attrs;
|
|
1539
|
+
}
|
|
1540
|
+
async function streamHydratableNodeToController(node, controller, encoder, ctx, isComponentRoot = false) {
|
|
1541
|
+
if (node == null || typeof node === "boolean") {
|
|
1542
|
+
return;
|
|
919
1543
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
return
|
|
1544
|
+
if (typeof node === "string") {
|
|
1545
|
+
enqueue(controller, encoder, escapeHtml(node));
|
|
1546
|
+
return;
|
|
923
1547
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
// src/index.ts
|
|
928
|
-
var exports_src = {};
|
|
929
|
-
__export(exports_src, {
|
|
930
|
-
unmountNode: () => unmountNode,
|
|
931
|
-
streamPage: () => streamPage,
|
|
932
|
-
signal: () => signal,
|
|
933
|
-
safeHtml: () => safeHtml,
|
|
934
|
-
renderToString: () => renderToString,
|
|
935
|
-
renderToHydratableString: () => renderToHydratableString,
|
|
936
|
-
renderPage: () => renderPage,
|
|
937
|
-
renderNodeToHydratableString: () => renderNodeToHydratableString,
|
|
938
|
-
renderNodeToDOM: () => renderNodeToDOM,
|
|
939
|
-
renderElementToDOM: () => renderElementToDOM,
|
|
940
|
-
render: () => render,
|
|
941
|
-
registerPage: () => registerPage,
|
|
942
|
-
raw: () => raw,
|
|
943
|
-
provide: () => provide,
|
|
944
|
-
onUpdated: () => onUpdated,
|
|
945
|
-
onUnmounted: () => onUnmounted,
|
|
946
|
-
onMounted: () => onMounted,
|
|
947
|
-
onError: () => onError,
|
|
948
|
-
nextTick: () => nextTick,
|
|
949
|
-
mount: () => mount,
|
|
950
|
-
jsxs: () => jsxs,
|
|
951
|
-
jsxDEV: () => jsxDEV,
|
|
952
|
-
jsx: () => jsx,
|
|
953
|
-
isSignal: () => isSignal,
|
|
954
|
-
isSafeHtml: () => isSafeHtml,
|
|
955
|
-
isComputed: () => isComputed,
|
|
956
|
-
inject: () => inject,
|
|
957
|
-
hydrate: () => hydrate,
|
|
958
|
-
hasPage: () => hasPage,
|
|
959
|
-
getPage: () => getPage,
|
|
960
|
-
getCurrentInstance: () => getCurrentInstance,
|
|
961
|
-
escapeHtml: () => escapeHtml,
|
|
962
|
-
effect: () => effect,
|
|
963
|
-
createPage: () => createPage,
|
|
964
|
-
createLayout: () => createLayout,
|
|
965
|
-
createComponent: () => createComponent,
|
|
966
|
-
computed: () => computed,
|
|
967
|
-
batch: () => batch,
|
|
968
|
-
HtmlEscapedString: () => HtmlEscapedString,
|
|
969
|
-
Fragment: () => Fragment
|
|
970
|
-
});
|
|
971
|
-
module.exports = __toCommonJS(exports_src);
|
|
972
|
-
// src/reactivity/batch.ts
|
|
973
|
-
var batchDepth = 0;
|
|
974
|
-
function batch(fn) {
|
|
975
|
-
batchDepth++;
|
|
976
|
-
try {
|
|
977
|
-
fn();
|
|
978
|
-
} finally {
|
|
979
|
-
batchDepth--;
|
|
980
|
-
if (batchDepth === 0) {
|
|
981
|
-
flushSync();
|
|
982
|
-
}
|
|
1548
|
+
if (typeof node === "number") {
|
|
1549
|
+
enqueue(controller, encoder, String(node));
|
|
1550
|
+
return;
|
|
983
1551
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
const instance = getCurrentInstance();
|
|
988
|
-
if (!instance) {
|
|
989
|
-
throw new Error("onMounted() called outside of component setup.");
|
|
1552
|
+
if (node instanceof HtmlEscapedString) {
|
|
1553
|
+
enqueue(controller, encoder, node.value);
|
|
1554
|
+
return;
|
|
990
1555
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
if (!instance) {
|
|
996
|
-
throw new Error("onUnmounted() called outside of component setup.");
|
|
1556
|
+
if (isSignal(node) || isComputed(node)) {
|
|
1557
|
+
const idx = ctx.textIndex++;
|
|
1558
|
+
enqueue(controller, encoder, `${textMarkerOpen(idx)}${escapeHtml(String(node.value))}${textMarkerCloseStr()}`);
|
|
1559
|
+
return;
|
|
997
1560
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
throw new Error("onUpdated() called outside of component setup.");
|
|
1561
|
+
if (Array.isArray(node)) {
|
|
1562
|
+
for (const child of node) {
|
|
1563
|
+
await streamHydratableNodeToController(child, controller, encoder, ctx);
|
|
1564
|
+
}
|
|
1565
|
+
return;
|
|
1004
1566
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
const instance = getCurrentInstance();
|
|
1009
|
-
if (!instance) {
|
|
1010
|
-
throw new Error("onError() called outside of component setup.");
|
|
1567
|
+
if (node instanceof Promise) {
|
|
1568
|
+
await streamHydratableElement(await node, controller, encoder, ctx, isComponentRoot);
|
|
1569
|
+
return;
|
|
1011
1570
|
}
|
|
1012
|
-
|
|
1013
|
-
}
|
|
1014
|
-
// src/component/create.ts
|
|
1015
|
-
function createComponent(fn) {
|
|
1016
|
-
const component = (props) => fn(props);
|
|
1017
|
-
component._SinwanComponent = true;
|
|
1018
|
-
component._displayName = fn.name || "AnonymousComponent";
|
|
1019
|
-
return component;
|
|
1020
|
-
}
|
|
1021
|
-
function createPage(fn) {
|
|
1022
|
-
const page = (data) => fn(data);
|
|
1023
|
-
page._SinwanPage = true;
|
|
1024
|
-
page._displayName = fn.name || "AnonymousPage";
|
|
1025
|
-
return page;
|
|
1026
|
-
}
|
|
1027
|
-
function createLayout(fn) {
|
|
1028
|
-
return createComponent(fn);
|
|
1571
|
+
await streamHydratableElement(node, controller, encoder, ctx, isComponentRoot);
|
|
1029
1572
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1573
|
+
async function streamHydratableElement(element, controller, encoder, ctx, isComponentRoot) {
|
|
1574
|
+
const { tag, props, children } = element;
|
|
1575
|
+
if (tag === "") {
|
|
1576
|
+
for (const child of children) {
|
|
1577
|
+
await streamHydratableNodeToController(child, controller, encoder, ctx);
|
|
1578
|
+
}
|
|
1579
|
+
return;
|
|
1035
1580
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
const instance = getCurrentInstance();
|
|
1040
|
-
if (!instance) {
|
|
1041
|
-
throw new Error("inject() called outside of component setup.");
|
|
1581
|
+
if (tag === Show || tag === For) {
|
|
1582
|
+
await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
|
|
1583
|
+
return;
|
|
1042
1584
|
}
|
|
1043
|
-
if (
|
|
1044
|
-
|
|
1585
|
+
if (isShowElement(element)) {
|
|
1586
|
+
const when = readReactive3(props.when);
|
|
1587
|
+
await streamHydratableNodeToController(when ? resolveShowChildren3(element, when) : props.fallback, controller, encoder, ctx, isComponentRoot);
|
|
1588
|
+
return;
|
|
1045
1589
|
}
|
|
1046
|
-
if (
|
|
1047
|
-
|
|
1590
|
+
if (isForElement(element)) {
|
|
1591
|
+
await streamHydratableForElement(element, controller, encoder, ctx);
|
|
1592
|
+
return;
|
|
1048
1593
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
// src/renderer/attributes.ts
|
|
1053
|
-
var SKIP_PROPS = new Set(["children", "key", "ref", "dangerouslySetInnerHTML"]);
|
|
1054
|
-
var DOM_PROPERTIES = new Set(["value", "checked", "selected", "disabled", "readOnly", "multiple", "indeterminate"]);
|
|
1055
|
-
var PROP_ALIASES = {
|
|
1056
|
-
className: "class",
|
|
1057
|
-
htmlFor: "for",
|
|
1058
|
-
tabIndex: "tabindex",
|
|
1059
|
-
crossOrigin: "crossorigin"
|
|
1060
|
-
};
|
|
1061
|
-
function applyAttributes(el, props) {
|
|
1062
|
-
const disposers = [];
|
|
1063
|
-
for (const [key, value] of Object.entries(props)) {
|
|
1064
|
-
if (SKIP_PROPS.has(key) || isEventProp(key))
|
|
1065
|
-
continue;
|
|
1066
|
-
if (isSignal(value) || isComputed(value)) {
|
|
1067
|
-
const dispose = effect(() => {
|
|
1068
|
-
setSingleAttribute(el, key, value.value);
|
|
1069
|
-
});
|
|
1070
|
-
disposers.push(dispose);
|
|
1071
|
-
} else {
|
|
1072
|
-
setSingleAttribute(el, key, value);
|
|
1073
|
-
}
|
|
1594
|
+
if (typeof tag === "function") {
|
|
1595
|
+
await streamHydratableComponent(tag, props, controller, encoder, ctx, true);
|
|
1596
|
+
return;
|
|
1074
1597
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
function setSingleAttribute(el, key, value) {
|
|
1078
|
-
const attrName = PROP_ALIASES[key] ?? key;
|
|
1079
|
-
if (attrName === "style" && typeof value === "object" && value !== null) {
|
|
1080
|
-
applyStyle(el, value);
|
|
1598
|
+
if (typeof tag === "string") {
|
|
1599
|
+
await streamHydratableIntrinsic(tag, props, children, controller, encoder, ctx, isComponentRoot);
|
|
1081
1600
|
return;
|
|
1082
1601
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1602
|
+
await streamHydratableNodeToController(children, controller, encoder, ctx);
|
|
1603
|
+
}
|
|
1604
|
+
async function streamHydratableComponent(component, props, controller, encoder, ctx, isComponentRoot) {
|
|
1605
|
+
const parentInstance = getCurrentInstance();
|
|
1606
|
+
const instance = createComponentInstance(component, props, parentInstance);
|
|
1607
|
+
if (parentInstance) {
|
|
1608
|
+
parentInstance.children.push(instance);
|
|
1609
|
+
}
|
|
1610
|
+
const prev = setCurrentInstance(instance);
|
|
1611
|
+
try {
|
|
1612
|
+
const result = await component(props);
|
|
1613
|
+
await streamHydratableNodeToController(result, controller, encoder, ctx, isComponentRoot);
|
|
1614
|
+
} finally {
|
|
1615
|
+
setCurrentInstance(prev);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
async function streamHydratableIntrinsic(tag, props, children, controller, encoder, ctx, isComponentRoot) {
|
|
1619
|
+
const attrs = renderHydratableAttributes(props, ctx, isComponentRoot);
|
|
1620
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
1621
|
+
enqueue(controller, encoder, attrs ? `<${tag}${attrs}>` : `<${tag}>`);
|
|
1622
|
+
if (VOID_ELEMENTS4.has(tag)) {
|
|
1085
1623
|
return;
|
|
1086
1624
|
}
|
|
1087
|
-
if (
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1625
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
1626
|
+
enqueue(controller, encoder, dangerous.__html);
|
|
1627
|
+
} else {
|
|
1628
|
+
for (const child of children) {
|
|
1629
|
+
await streamHydratableNodeToController(child, controller, encoder, ctx);
|
|
1091
1630
|
}
|
|
1631
|
+
}
|
|
1632
|
+
enqueue(controller, encoder, `</${tag}>`);
|
|
1633
|
+
}
|
|
1634
|
+
async function streamHydratableForElement(element, controller, encoder, ctx) {
|
|
1635
|
+
const props = element.props;
|
|
1636
|
+
const each = readReactive3(props.each);
|
|
1637
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1092
1638
|
return;
|
|
1093
1639
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1640
|
+
for (let index = 0;index < each.length; index++) {
|
|
1641
|
+
await streamHydratableNodeToController(props.children(each[index], () => index), controller, encoder, ctx);
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
function renderHydratableAttributes(props, ctx, isComponentRoot) {
|
|
1645
|
+
let attrs = "";
|
|
1646
|
+
if (isComponentRoot) {
|
|
1647
|
+
attrs += ` ${COMP_ID_ATTR}="${compId(ctx.componentIndex++)}"`;
|
|
1648
|
+
}
|
|
1649
|
+
const eventParts = [];
|
|
1650
|
+
for (const [key, value] of Object.entries(props)) {
|
|
1651
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML") {
|
|
1652
|
+
continue;
|
|
1098
1653
|
}
|
|
1099
|
-
|
|
1654
|
+
if (isEventProp(key)) {
|
|
1655
|
+
eventParts.push(`${toEventName(key)}:${ctx.eventIndex++}`);
|
|
1656
|
+
continue;
|
|
1657
|
+
}
|
|
1658
|
+
const resolvedValue = readReactive3(value);
|
|
1659
|
+
if (resolvedValue == null || resolvedValue === false)
|
|
1660
|
+
continue;
|
|
1661
|
+
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
1662
|
+
if (resolvedValue === true) {
|
|
1663
|
+
attrs += ` ${attrName}`;
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1666
|
+
attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
|
|
1100
1667
|
}
|
|
1101
|
-
if (
|
|
1102
|
-
|
|
1668
|
+
if (eventParts.length > 0) {
|
|
1669
|
+
attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
|
|
1670
|
+
}
|
|
1671
|
+
return attrs;
|
|
1672
|
+
}
|
|
1673
|
+
function enqueue(controller, encoder, html) {
|
|
1674
|
+
controller.enqueue(encoder.encode(html));
|
|
1675
|
+
}
|
|
1676
|
+
async function streamForElement(element, controller, encoder) {
|
|
1677
|
+
const props = element.props;
|
|
1678
|
+
const each = readReactive3(props.each);
|
|
1679
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1103
1680
|
return;
|
|
1104
1681
|
}
|
|
1105
|
-
|
|
1682
|
+
for (let index = 0;index < each.length; index++) {
|
|
1683
|
+
await streamNode(props.children(each[index], () => index), controller, encoder);
|
|
1684
|
+
}
|
|
1106
1685
|
}
|
|
1107
|
-
function
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
} else {
|
|
1112
|
-
el.style[prop] = val;
|
|
1113
|
-
}
|
|
1686
|
+
function resolveShowChildren3(element, value) {
|
|
1687
|
+
const children = element.props.children ?? element.children;
|
|
1688
|
+
if (typeof children === "function") {
|
|
1689
|
+
return children(value);
|
|
1114
1690
|
}
|
|
1691
|
+
return children;
|
|
1115
1692
|
}
|
|
1116
|
-
function
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1693
|
+
function readReactive3(value) {
|
|
1694
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
1695
|
+
}
|
|
1696
|
+
// src/server/hydration-markers.ts
|
|
1697
|
+
function createHydrationContext() {
|
|
1698
|
+
return { componentIndex: 0, textIndex: 0, eventIndex: 0 };
|
|
1699
|
+
}
|
|
1700
|
+
async function renderToHydratableString(component, props) {
|
|
1701
|
+
const ctx = createHydrationContext();
|
|
1702
|
+
const mergedProps = props ?? {};
|
|
1703
|
+
const instance = createComponentInstance(component, mergedProps, null);
|
|
1704
|
+
const prev = setCurrentInstance(instance);
|
|
1705
|
+
try {
|
|
1706
|
+
const result = await component(mergedProps);
|
|
1707
|
+
if (result && typeof result === "object" && "tag" in result) {
|
|
1708
|
+
return renderElementH(result, ctx, true);
|
|
1709
|
+
}
|
|
1710
|
+
return renderNodeH(result, ctx);
|
|
1711
|
+
} finally {
|
|
1712
|
+
setCurrentInstance(prev);
|
|
1124
1713
|
}
|
|
1125
|
-
domOps.setAttribute(el, "class", classStr);
|
|
1126
1714
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1715
|
+
async function renderNodeToHydratableString(node) {
|
|
1716
|
+
const ctx = createHydrationContext();
|
|
1717
|
+
return renderNodeH(node, ctx);
|
|
1718
|
+
}
|
|
1129
1719
|
var VOID_ELEMENTS5 = new Set([
|
|
1130
1720
|
"area",
|
|
1131
1721
|
"base",
|
|
@@ -1142,273 +1732,269 @@ var VOID_ELEMENTS5 = new Set([
|
|
|
1142
1732
|
"track",
|
|
1143
1733
|
"wbr"
|
|
1144
1734
|
]);
|
|
1145
|
-
function
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1735
|
+
function renderNodeH(node, ctx) {
|
|
1736
|
+
if (node == null || typeof node === "boolean")
|
|
1737
|
+
return "";
|
|
1738
|
+
if (typeof node === "string")
|
|
1739
|
+
return escapeHtml(node);
|
|
1740
|
+
if (typeof node === "number")
|
|
1741
|
+
return String(node);
|
|
1742
|
+
if (node instanceof HtmlEscapedString)
|
|
1743
|
+
return node.value;
|
|
1744
|
+
if (isSignal(node) || isComputed(node)) {
|
|
1745
|
+
const value = node.value;
|
|
1746
|
+
const idx = ctx.textIndex++;
|
|
1747
|
+
return `${textMarkerOpen(idx)}${escapeHtml(String(value))}${textMarkerCloseStr()}`;
|
|
1149
1748
|
}
|
|
1150
|
-
if (
|
|
1151
|
-
return
|
|
1749
|
+
if (Array.isArray(node)) {
|
|
1750
|
+
return node.map((child) => renderNodeH(child, ctx)).join("");
|
|
1152
1751
|
}
|
|
1153
|
-
if (
|
|
1154
|
-
return
|
|
1752
|
+
if (node instanceof Promise) {
|
|
1753
|
+
return "";
|
|
1754
|
+
}
|
|
1755
|
+
if (typeof node === "object" && "tag" in node) {
|
|
1756
|
+
return renderElementH(node, ctx, false);
|
|
1155
1757
|
}
|
|
1156
|
-
return
|
|
1758
|
+
return escapeHtml(String(node));
|
|
1157
1759
|
}
|
|
1158
|
-
function
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
let mountedChildren = [];
|
|
1163
|
-
if (!VOID_ELEMENTS5.has(tag)) {
|
|
1164
|
-
const dangerous = props.dangerouslySetInnerHTML;
|
|
1165
|
-
if (dangerous && typeof dangerous.__html === "string") {
|
|
1166
|
-
el.innerHTML = dangerous.__html;
|
|
1167
|
-
} else {
|
|
1168
|
-
mountedChildren = renderChildrenToDOM(children, el);
|
|
1169
|
-
}
|
|
1760
|
+
function renderElementH(element, ctx, isComponentRoot) {
|
|
1761
|
+
const { tag, props, children } = element;
|
|
1762
|
+
if (tag === "") {
|
|
1763
|
+
return children.map((child) => renderNodeH(child, ctx)).join("");
|
|
1170
1764
|
}
|
|
1171
|
-
if (
|
|
1172
|
-
|
|
1173
|
-
} else {
|
|
1174
|
-
domOps.appendChild(parent, el);
|
|
1765
|
+
if (tag === Show || tag === For) {
|
|
1766
|
+
return renderElementH(tag(props), ctx, isComponentRoot);
|
|
1175
1767
|
}
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1768
|
+
if (isShowElement(element)) {
|
|
1769
|
+
const when = readReactive4(props.when);
|
|
1770
|
+
const content = when ? resolveShowChildren4(element, when) : props.fallback;
|
|
1771
|
+
return renderNodeMaybeRoot(content, ctx, isComponentRoot);
|
|
1772
|
+
}
|
|
1773
|
+
if (isForElement(element)) {
|
|
1774
|
+
return renderForElementH(element, ctx);
|
|
1775
|
+
}
|
|
1776
|
+
if (typeof tag === "function") {
|
|
1777
|
+
return renderComponentH(tag, props, ctx);
|
|
1778
|
+
}
|
|
1779
|
+
if (typeof tag === "string") {
|
|
1780
|
+
return renderIntrinsicH(tag, props, children, ctx, isComponentRoot);
|
|
1781
|
+
}
|
|
1782
|
+
return children.map((child) => renderNodeH(child, ctx)).join("");
|
|
1183
1783
|
}
|
|
1184
|
-
function
|
|
1784
|
+
function renderComponentH(component, props, ctx) {
|
|
1185
1785
|
const parentInstance = getCurrentInstance();
|
|
1186
1786
|
const instance = createComponentInstance(component, props, parentInstance);
|
|
1187
1787
|
if (parentInstance) {
|
|
1188
1788
|
parentInstance.children.push(instance);
|
|
1189
1789
|
}
|
|
1190
|
-
const
|
|
1191
|
-
let result;
|
|
1192
|
-
let child;
|
|
1790
|
+
const prev = setCurrentInstance(instance);
|
|
1193
1791
|
try {
|
|
1194
|
-
result = component(props);
|
|
1792
|
+
const result = component(props);
|
|
1195
1793
|
if (result && typeof result === "object" && "tag" in result) {
|
|
1196
|
-
|
|
1197
|
-
} else {
|
|
1198
|
-
child = renderNodeToDOM(result, parent, anchor);
|
|
1199
|
-
}
|
|
1200
|
-
} catch (err) {
|
|
1201
|
-
setCurrentInstance(prevInstance);
|
|
1202
|
-
handleComponentError(instance, err);
|
|
1203
|
-
const text = domOps.createTextNode("");
|
|
1204
|
-
if (anchor) {
|
|
1205
|
-
domOps.insertBefore(parent, text, anchor);
|
|
1206
|
-
} else {
|
|
1207
|
-
domOps.appendChild(parent, text);
|
|
1794
|
+
return renderElementH(result, ctx, true);
|
|
1208
1795
|
}
|
|
1209
|
-
return
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
disposers: [],
|
|
1213
|
-
instance
|
|
1214
|
-
};
|
|
1215
|
-
}
|
|
1216
|
-
setCurrentInstance(prevInstance);
|
|
1217
|
-
instance.element = child;
|
|
1218
|
-
return {
|
|
1219
|
-
type: "component",
|
|
1220
|
-
children: [child],
|
|
1221
|
-
disposers: instance.effects,
|
|
1222
|
-
instance
|
|
1223
|
-
};
|
|
1224
|
-
}
|
|
1225
|
-
function renderFragmentToDOM(children, parent, anchor) {
|
|
1226
|
-
const anchorComment = domOps.createComment("Sinwan-f");
|
|
1227
|
-
if (anchor) {
|
|
1228
|
-
domOps.insertBefore(parent, anchorComment, anchor);
|
|
1229
|
-
} else {
|
|
1230
|
-
domOps.appendChild(parent, anchorComment);
|
|
1231
|
-
}
|
|
1232
|
-
const mounted = [];
|
|
1233
|
-
for (const child of children) {
|
|
1234
|
-
mounted.push(renderNodeToDOM(child, parent, anchor));
|
|
1796
|
+
return renderNodeH(result, ctx);
|
|
1797
|
+
} finally {
|
|
1798
|
+
setCurrentInstance(prev);
|
|
1235
1799
|
}
|
|
1236
|
-
return { type: "fragment", children: mounted, anchor: anchorComment };
|
|
1237
1800
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
const text2 = domOps.createTextNode("");
|
|
1243
|
-
insertNode(parent, text2, anchor);
|
|
1244
|
-
return { type: "text", node: text2 };
|
|
1245
|
-
}
|
|
1246
|
-
if (typeof node === "string") {
|
|
1247
|
-
const text2 = domOps.createTextNode(node);
|
|
1248
|
-
insertNode(parent, text2, anchor);
|
|
1249
|
-
return { type: "text", node: text2 };
|
|
1250
|
-
}
|
|
1251
|
-
if (typeof node === "number") {
|
|
1252
|
-
const text2 = domOps.createTextNode(String(node));
|
|
1253
|
-
insertNode(parent, text2, anchor);
|
|
1254
|
-
return { type: "text", node: text2 };
|
|
1255
|
-
}
|
|
1256
|
-
if (node instanceof HtmlEscapedString) {
|
|
1257
|
-
const text2 = domOps.createTextNode(node.value);
|
|
1258
|
-
insertNode(parent, text2, anchor);
|
|
1259
|
-
return { type: "text", node: text2 };
|
|
1260
|
-
}
|
|
1261
|
-
if (isSignal(node) || isComputed(node)) {
|
|
1262
|
-
const text2 = domOps.createTextNode(String(node.value));
|
|
1263
|
-
insertNode(parent, text2, anchor);
|
|
1264
|
-
const dispose = effect(() => {
|
|
1265
|
-
domOps.setTextContent(text2, String(node.value));
|
|
1266
|
-
});
|
|
1267
|
-
return { type: "reactive-text", node: text2, dispose };
|
|
1801
|
+
function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
|
|
1802
|
+
let attrs = "";
|
|
1803
|
+
if (isComponentRoot) {
|
|
1804
|
+
attrs += ` ${COMP_ID_ATTR}="${compId(ctx.componentIndex++)}"`;
|
|
1268
1805
|
}
|
|
1269
|
-
|
|
1270
|
-
|
|
1806
|
+
const eventParts = [];
|
|
1807
|
+
for (const [key, value] of Object.entries(props)) {
|
|
1808
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML") {
|
|
1809
|
+
continue;
|
|
1810
|
+
}
|
|
1811
|
+
if (isEventProp(key)) {
|
|
1812
|
+
const eventName = toEventName(key);
|
|
1813
|
+
eventParts.push(`${eventName}:${ctx.eventIndex++}`);
|
|
1814
|
+
continue;
|
|
1815
|
+
}
|
|
1816
|
+
if (value == null || value === false)
|
|
1817
|
+
continue;
|
|
1818
|
+
let resolvedValue = value;
|
|
1819
|
+
if (isSignal(value) || isComputed(value)) {
|
|
1820
|
+
resolvedValue = value.value;
|
|
1821
|
+
}
|
|
1822
|
+
if (resolvedValue === true) {
|
|
1823
|
+
const attrName2 = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
1824
|
+
attrs += ` ${attrName2}`;
|
|
1825
|
+
continue;
|
|
1826
|
+
}
|
|
1827
|
+
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
1828
|
+
attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
|
|
1271
1829
|
}
|
|
1272
|
-
if (
|
|
1273
|
-
|
|
1274
|
-
insertNode(parent, placeholder, anchor);
|
|
1275
|
-
node.then((resolved) => {
|
|
1276
|
-
const mounted = renderNodeToDOM(resolved, parent, placeholder);
|
|
1277
|
-
domOps.remove(placeholder);
|
|
1278
|
-
});
|
|
1279
|
-
return { type: "text", node: placeholder };
|
|
1830
|
+
if (eventParts.length > 0) {
|
|
1831
|
+
attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
|
|
1280
1832
|
}
|
|
1281
|
-
if (
|
|
1282
|
-
return
|
|
1833
|
+
if (VOID_ELEMENTS5.has(tag)) {
|
|
1834
|
+
return `<${tag}${attrs}>`;
|
|
1283
1835
|
}
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
|
|
1836
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
1837
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
1838
|
+
return `<${tag}${attrs}>${dangerous.__html}</${tag}>`;
|
|
1839
|
+
}
|
|
1840
|
+
const childrenHtml = children.map((child) => renderNodeH(child, ctx)).join("");
|
|
1841
|
+
return `<${tag}${attrs}>${childrenHtml}</${tag}>`;
|
|
1287
1842
|
}
|
|
1288
|
-
function
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
const children = [];
|
|
1292
|
-
for (const child of nodes) {
|
|
1293
|
-
children.push(renderNodeToDOM(child, parent, anchor));
|
|
1843
|
+
function renderNodeMaybeRoot(node, ctx, isComponentRoot) {
|
|
1844
|
+
if (isComponentRoot && node && typeof node === "object" && !Array.isArray(node) && "tag" in node) {
|
|
1845
|
+
return renderElementH(node, ctx, true);
|
|
1294
1846
|
}
|
|
1295
|
-
return
|
|
1847
|
+
return renderNodeH(node, ctx);
|
|
1296
1848
|
}
|
|
1297
|
-
function
|
|
1298
|
-
const
|
|
1299
|
-
|
|
1300
|
-
|
|
1849
|
+
function renderForElementH(element, ctx) {
|
|
1850
|
+
const props = element.props;
|
|
1851
|
+
const each = readReactive4(props.each);
|
|
1852
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1853
|
+
return "";
|
|
1301
1854
|
}
|
|
1302
|
-
return
|
|
1855
|
+
return each.map((item, index) => renderNodeH(props.children(item, () => index), ctx)).join("");
|
|
1303
1856
|
}
|
|
1304
|
-
function
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
domOps.appendChild(parent, child);
|
|
1857
|
+
function resolveShowChildren4(element, value) {
|
|
1858
|
+
const children = element.props.children ?? element.children;
|
|
1859
|
+
if (typeof children === "function") {
|
|
1860
|
+
return children(value);
|
|
1309
1861
|
}
|
|
1862
|
+
return children;
|
|
1310
1863
|
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1864
|
+
function readReactive4(value) {
|
|
1865
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
1866
|
+
}
|
|
1867
|
+
// src/index.ts
|
|
1868
|
+
var exports_src = {};
|
|
1869
|
+
__export(exports_src, {
|
|
1870
|
+
unmountNode: () => unmountNode,
|
|
1871
|
+
streamPage: () => streamPage,
|
|
1872
|
+
streamHydratablePage: () => streamHydratablePage,
|
|
1873
|
+
streamHydratableNode: () => streamHydratableNode,
|
|
1874
|
+
signal: () => signal,
|
|
1875
|
+
setDOMOps: () => setDOMOps,
|
|
1876
|
+
safeHtml: () => safeHtml,
|
|
1877
|
+
resetDOMOps: () => resetDOMOps,
|
|
1878
|
+
renderToString: () => renderToString,
|
|
1879
|
+
renderToHydratableString: () => renderToHydratableString,
|
|
1880
|
+
renderPage: () => renderPage,
|
|
1881
|
+
renderNodeToHydratableString: () => renderNodeToHydratableString,
|
|
1882
|
+
renderNodeToDOM: () => renderNodeToDOM,
|
|
1883
|
+
renderElementToDOM: () => renderElementToDOM,
|
|
1884
|
+
render: () => render,
|
|
1885
|
+
registerPage: () => registerPage,
|
|
1886
|
+
raw: () => raw,
|
|
1887
|
+
provide: () => provide,
|
|
1888
|
+
onUpdated: () => onUpdated,
|
|
1889
|
+
onUnmounted: () => onUnmounted,
|
|
1890
|
+
onMounted: () => onMounted,
|
|
1891
|
+
onError: () => onError,
|
|
1892
|
+
nextTick: () => nextTick,
|
|
1893
|
+
mount: () => mount,
|
|
1894
|
+
jsxs: () => jsxs,
|
|
1895
|
+
jsxDEV: () => jsxDEV,
|
|
1896
|
+
jsx: () => jsx,
|
|
1897
|
+
isSignal: () => isSignal,
|
|
1898
|
+
isSafeHtml: () => isSafeHtml,
|
|
1899
|
+
isComputed: () => isComputed,
|
|
1900
|
+
inject: () => inject,
|
|
1901
|
+
hydrate: () => hydrate,
|
|
1902
|
+
hasPage: () => hasPage,
|
|
1903
|
+
getPage: () => getPage,
|
|
1904
|
+
getCurrentInstance: () => getCurrentInstance,
|
|
1905
|
+
escapeHtml: () => escapeHtml,
|
|
1906
|
+
effect: () => effect,
|
|
1907
|
+
domOps: () => domOps,
|
|
1908
|
+
createPage: () => createPage,
|
|
1909
|
+
createLayout: () => createLayout,
|
|
1910
|
+
createComponent: () => createComponent,
|
|
1911
|
+
computed: () => computed,
|
|
1912
|
+
batch: () => batch,
|
|
1913
|
+
Show: () => Show,
|
|
1914
|
+
HtmlEscapedString: () => HtmlEscapedString,
|
|
1915
|
+
Fragment: () => Fragment,
|
|
1916
|
+
For: () => For
|
|
1917
|
+
});
|
|
1918
|
+
module.exports = __toCommonJS(exports_src);
|
|
1919
|
+
// src/reactivity/batch.ts
|
|
1920
|
+
var batchDepth = 0;
|
|
1921
|
+
function batch(fn) {
|
|
1922
|
+
batchDepth++;
|
|
1320
1923
|
try {
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
result.then((resolved) => {
|
|
1327
|
-
container.innerHTML = "";
|
|
1328
|
-
setCurrentInstance(instance);
|
|
1329
|
-
root = renderElementToDOM(resolved, container);
|
|
1330
|
-
setCurrentInstance(null);
|
|
1331
|
-
instance.element = root;
|
|
1332
|
-
fireMountedHooks(instance);
|
|
1333
|
-
});
|
|
1334
|
-
} else if (result && typeof result === "object" && "tag" in result) {
|
|
1335
|
-
root = renderElementToDOM(result, container);
|
|
1336
|
-
} else {
|
|
1337
|
-
root = renderNodeToDOM(result, container);
|
|
1924
|
+
fn();
|
|
1925
|
+
} finally {
|
|
1926
|
+
batchDepth--;
|
|
1927
|
+
if (batchDepth === 0) {
|
|
1928
|
+
flushSync();
|
|
1338
1929
|
}
|
|
1339
|
-
} catch (err) {
|
|
1340
|
-
setCurrentInstance(null);
|
|
1341
|
-
handleComponentError(instance, err);
|
|
1342
|
-
return {
|
|
1343
|
-
root: { type: "text", node: document.createTextNode("") },
|
|
1344
|
-
unmount() {}
|
|
1345
|
-
};
|
|
1346
1930
|
}
|
|
1347
|
-
setCurrentInstance(null);
|
|
1348
|
-
instance.element = root;
|
|
1349
|
-
fireMountedHooks(instance);
|
|
1350
|
-
return {
|
|
1351
|
-
root,
|
|
1352
|
-
unmount() {
|
|
1353
|
-
fireUnmountedHooks(instance);
|
|
1354
|
-
unmountNode(root);
|
|
1355
|
-
container.innerHTML = "";
|
|
1356
|
-
}
|
|
1357
|
-
};
|
|
1358
1931
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
const
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
container.innerHTML = "";
|
|
1367
|
-
}
|
|
1368
|
-
};
|
|
1932
|
+
// src/component/lifecycle.ts
|
|
1933
|
+
function onMounted(fn) {
|
|
1934
|
+
const instance = getCurrentInstance();
|
|
1935
|
+
if (!instance) {
|
|
1936
|
+
throw new Error("onMounted() called outside of component setup.");
|
|
1937
|
+
}
|
|
1938
|
+
instance._mountedHooks.push(() => withInstance(instance, fn));
|
|
1369
1939
|
}
|
|
1370
|
-
function
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1940
|
+
function onUnmounted(fn) {
|
|
1941
|
+
const instance = getCurrentInstance();
|
|
1942
|
+
if (!instance) {
|
|
1943
|
+
throw new Error("onUnmounted() called outside of component setup.");
|
|
1944
|
+
}
|
|
1945
|
+
instance._unmountedHooks.push(() => withInstance(instance, fn));
|
|
1946
|
+
}
|
|
1947
|
+
function onUpdated(fn) {
|
|
1948
|
+
const instance = getCurrentInstance();
|
|
1949
|
+
if (!instance) {
|
|
1950
|
+
throw new Error("onUpdated() called outside of component setup.");
|
|
1951
|
+
}
|
|
1952
|
+
instance._updatedHooks.push(() => withInstance(instance, fn));
|
|
1953
|
+
}
|
|
1954
|
+
function onError(fn) {
|
|
1955
|
+
const instance = getCurrentInstance();
|
|
1956
|
+
if (!instance) {
|
|
1957
|
+
throw new Error("onError() called outside of component setup.");
|
|
1958
|
+
}
|
|
1959
|
+
instance._errorHooks.push((err) => withInstance(instance, () => fn(err)));
|
|
1960
|
+
}
|
|
1961
|
+
// src/component/create.ts
|
|
1962
|
+
function createComponent(fn) {
|
|
1963
|
+
const component = (props) => fn(props);
|
|
1964
|
+
component._SinwanComponent = true;
|
|
1965
|
+
component._displayName = fn.name || "AnonymousComponent";
|
|
1966
|
+
return component;
|
|
1967
|
+
}
|
|
1968
|
+
function createPage(fn) {
|
|
1969
|
+
const page = (data) => fn(data);
|
|
1970
|
+
page._SinwanPage = true;
|
|
1971
|
+
page._displayName = fn.name || "AnonymousPage";
|
|
1972
|
+
return page;
|
|
1973
|
+
}
|
|
1974
|
+
function createLayout(fn) {
|
|
1975
|
+
return createComponent(fn);
|
|
1976
|
+
}
|
|
1977
|
+
// src/component/provide-inject.ts
|
|
1978
|
+
function provide(key, value) {
|
|
1979
|
+
const instance = getCurrentInstance();
|
|
1980
|
+
if (!instance) {
|
|
1981
|
+
throw new Error("provide() called outside of component setup.");
|
|
1982
|
+
}
|
|
1983
|
+
instance.provides[key] = value;
|
|
1984
|
+
}
|
|
1985
|
+
function inject(key, defaultValue) {
|
|
1986
|
+
const instance = getCurrentInstance();
|
|
1987
|
+
if (!instance) {
|
|
1988
|
+
throw new Error("inject() called outside of component setup.");
|
|
1989
|
+
}
|
|
1990
|
+
if (key in instance.provides) {
|
|
1991
|
+
return instance.provides[key];
|
|
1992
|
+
}
|
|
1993
|
+
if (arguments.length >= 2) {
|
|
1994
|
+
return defaultValue;
|
|
1411
1995
|
}
|
|
1996
|
+
console.warn(`[Sinwan] inject() key "${String(key)}" not found and no default provided.`);
|
|
1997
|
+
return;
|
|
1412
1998
|
}
|
|
1413
1999
|
// src/hydration/walk.ts
|
|
1414
2000
|
function advance(cursor) {
|
|
@@ -1449,6 +2035,7 @@ function hydrateNode(node, cursor) {
|
|
|
1449
2035
|
}
|
|
1450
2036
|
function hydrateReactiveText(reactive, cursor) {
|
|
1451
2037
|
const openComment = cursor.current;
|
|
2038
|
+
const owner = getCurrentInstance();
|
|
1452
2039
|
if (openComment && openComment.nodeType === 8 && parseTextOpenMarker(openComment) >= 0) {
|
|
1453
2040
|
advance(cursor);
|
|
1454
2041
|
const textNode2 = advance(cursor);
|
|
@@ -1456,21 +2043,36 @@ function hydrateReactiveText(reactive, cursor) {
|
|
|
1456
2043
|
if (closeComment && closeComment.nodeType === 8 && isTextCloseMarker(closeComment)) {
|
|
1457
2044
|
advance(cursor);
|
|
1458
2045
|
}
|
|
2046
|
+
let initialized2 = false;
|
|
1459
2047
|
const dispose2 = effect(() => {
|
|
1460
2048
|
textNode2.data = String(reactive.value);
|
|
2049
|
+
if (initialized2) {
|
|
2050
|
+
queueUpdatedHooks(owner);
|
|
2051
|
+
}
|
|
2052
|
+
initialized2 = true;
|
|
1461
2053
|
});
|
|
1462
2054
|
return { type: "reactive-text", node: textNode2, dispose: dispose2 };
|
|
1463
2055
|
}
|
|
1464
2056
|
const textNode = advance(cursor);
|
|
1465
2057
|
if (textNode) {
|
|
2058
|
+
let initialized2 = false;
|
|
1466
2059
|
const dispose2 = effect(() => {
|
|
1467
2060
|
textNode.data = String(reactive.value);
|
|
2061
|
+
if (initialized2) {
|
|
2062
|
+
queueUpdatedHooks(owner);
|
|
2063
|
+
}
|
|
2064
|
+
initialized2 = true;
|
|
1468
2065
|
});
|
|
1469
2066
|
return { type: "reactive-text", node: textNode, dispose: dispose2 };
|
|
1470
2067
|
}
|
|
1471
2068
|
const newText = document.createTextNode(String(reactive.value));
|
|
2069
|
+
let initialized = false;
|
|
1472
2070
|
const dispose = effect(() => {
|
|
1473
2071
|
newText.data = String(reactive.value);
|
|
2072
|
+
if (initialized) {
|
|
2073
|
+
queueUpdatedHooks(owner);
|
|
2074
|
+
}
|
|
2075
|
+
initialized = true;
|
|
1474
2076
|
});
|
|
1475
2077
|
return { type: "reactive-text", node: newText, dispose };
|
|
1476
2078
|
}
|
|
@@ -1479,6 +2081,12 @@ function hydrateElement(element, cursor) {
|
|
|
1479
2081
|
if (tag === "") {
|
|
1480
2082
|
return hydrateArray(children, cursor);
|
|
1481
2083
|
}
|
|
2084
|
+
if (tag === Show || tag === For) {
|
|
2085
|
+
return hydrateElement(tag(props), cursor);
|
|
2086
|
+
}
|
|
2087
|
+
if (isShowElement(element) || isForElement(element)) {
|
|
2088
|
+
return hydrateControlFlow(element, cursor);
|
|
2089
|
+
}
|
|
1482
2090
|
if (typeof tag === "function") {
|
|
1483
2091
|
return hydrateComponent(tag, props, cursor);
|
|
1484
2092
|
}
|
|
@@ -1497,6 +2105,7 @@ function hydrateIntrinsic(tag, props, children, cursor) {
|
|
|
1497
2105
|
el.removeAttribute("data-sinwan-ev");
|
|
1498
2106
|
const attrDisposers = hydrateAttributes(el, props);
|
|
1499
2107
|
const eventCleanups = bindEvents(el, props);
|
|
2108
|
+
const refCleanup = applyRef2(el, props.ref);
|
|
1500
2109
|
const childCursor = {
|
|
1501
2110
|
parent: el,
|
|
1502
2111
|
current: el.firstChild
|
|
@@ -1510,15 +2119,18 @@ function hydrateIntrinsic(tag, props, children, cursor) {
|
|
|
1510
2119
|
node: el,
|
|
1511
2120
|
children: mountedChildren,
|
|
1512
2121
|
eventCleanups,
|
|
1513
|
-
attrDisposers
|
|
2122
|
+
attrDisposers,
|
|
2123
|
+
refCleanup
|
|
1514
2124
|
};
|
|
1515
2125
|
}
|
|
1516
2126
|
function hydrateAttributes(el, props) {
|
|
1517
2127
|
const disposers = [];
|
|
2128
|
+
const owner = getCurrentInstance();
|
|
1518
2129
|
for (const [key, value] of Object.entries(props)) {
|
|
1519
2130
|
if (key === "children" || key === "key" || key === "ref" || isEventProp(key))
|
|
1520
2131
|
continue;
|
|
1521
2132
|
if (isSignal(value) || isComputed(value)) {
|
|
2133
|
+
let initialized = false;
|
|
1522
2134
|
const dispose = effect(() => {
|
|
1523
2135
|
const v = value.value;
|
|
1524
2136
|
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
@@ -1529,12 +2141,63 @@ function hydrateAttributes(el, props) {
|
|
|
1529
2141
|
} else {
|
|
1530
2142
|
el.setAttribute(attrName, String(v));
|
|
1531
2143
|
}
|
|
2144
|
+
if (initialized) {
|
|
2145
|
+
queueUpdatedHooks(owner);
|
|
2146
|
+
}
|
|
2147
|
+
initialized = true;
|
|
1532
2148
|
});
|
|
1533
2149
|
disposers.push(dispose);
|
|
1534
2150
|
}
|
|
1535
2151
|
}
|
|
1536
2152
|
return disposers;
|
|
1537
2153
|
}
|
|
2154
|
+
function hydrateControlFlow(element, cursor) {
|
|
2155
|
+
if (isShowElement(element)) {
|
|
2156
|
+
const when = readReactive5(element.props.when);
|
|
2157
|
+
const content = when ? resolveShowChildren5(element, when) : element.props.fallback;
|
|
2158
|
+
return hydrateContent(content, cursor);
|
|
2159
|
+
}
|
|
2160
|
+
if (isForElement(element)) {
|
|
2161
|
+
const props = element.props;
|
|
2162
|
+
const items = readReactive5(props.each);
|
|
2163
|
+
const children = Array.isArray(items) && typeof props.children === "function" ? items.map((item, index) => props.children(item, () => index)) : [];
|
|
2164
|
+
return hydrateArray(children, cursor);
|
|
2165
|
+
}
|
|
2166
|
+
return hydrateArray(element.children, cursor);
|
|
2167
|
+
}
|
|
2168
|
+
function hydrateContent(content, cursor) {
|
|
2169
|
+
if (content == null || typeof content === "boolean") {
|
|
2170
|
+
return hydrateArray([], cursor);
|
|
2171
|
+
}
|
|
2172
|
+
return Array.isArray(content) ? hydrateArray(content, cursor) : hydrateNode(content, cursor);
|
|
2173
|
+
}
|
|
2174
|
+
function resolveShowChildren5(element, value) {
|
|
2175
|
+
const children = element.props.children ?? element.children;
|
|
2176
|
+
if (typeof children === "function") {
|
|
2177
|
+
return children(value);
|
|
2178
|
+
}
|
|
2179
|
+
return children;
|
|
2180
|
+
}
|
|
2181
|
+
function readReactive5(value) {
|
|
2182
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
2183
|
+
}
|
|
2184
|
+
function applyRef2(el, ref) {
|
|
2185
|
+
const value = ref;
|
|
2186
|
+
if (!value) {
|
|
2187
|
+
return null;
|
|
2188
|
+
}
|
|
2189
|
+
if (typeof value === "function") {
|
|
2190
|
+
value(el);
|
|
2191
|
+
return () => value(null);
|
|
2192
|
+
}
|
|
2193
|
+
if (typeof value === "object" && "current" in value) {
|
|
2194
|
+
value.current = el;
|
|
2195
|
+
return () => {
|
|
2196
|
+
value.current = null;
|
|
2197
|
+
};
|
|
2198
|
+
}
|
|
2199
|
+
return null;
|
|
2200
|
+
}
|
|
1538
2201
|
function hydrateComponent(component, props, cursor) {
|
|
1539
2202
|
const parentInstance = getCurrentInstance();
|
|
1540
2203
|
const instance = createComponentInstance(component, props, parentInstance);
|
|
@@ -1621,5 +2284,5 @@ function hydrate(component, container, props) {
|
|
|
1621
2284
|
};
|
|
1622
2285
|
}
|
|
1623
2286
|
|
|
1624
|
-
//# debugId=
|
|
2287
|
+
//# debugId=82414CC0A24D81DC64756E2164756E21
|
|
1625
2288
|
//# sourceMappingURL=index.development.js.map
|