sibujs 4.6.0 → 4.8.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 +1 -1
- package/dist/browser.cjs +62 -8
- package/dist/browser.d.cts +23 -0
- package/dist/browser.d.ts +23 -0
- package/dist/browser.js +6 -5
- package/dist/build.cjs +2388 -1004
- package/dist/build.d.cts +147 -44
- package/dist/build.d.ts +147 -44
- package/dist/build.js +1410 -564
- package/dist/cdn.dev.global.js +14 -12
- package/dist/cdn.full.dev.global.js +15 -13
- package/dist/cdn.full.global.js +14 -12
- package/dist/cdn.global.js +12 -10
- package/dist/chunk-3ACAAQIN.js +224 -0
- package/dist/{chunk-7NCARGJW.js → chunk-44MTL7ED.js} +6 -6
- package/dist/{chunk-BAAG6ZTI.js → chunk-4WMSTZ7J.js} +8 -5
- package/dist/{chunk-H3SRKIYX.js → chunk-62BDYGAG.js} +8 -0
- package/dist/{chunk-DKGBBKOF.js → chunk-C5PEWEGH.js} +20 -5
- package/dist/{chunk-3ISI6ACU.js → chunk-C7AA2CZX.js} +1 -1
- package/dist/{chunk-UZQ6ALFS.js → chunk-CZPRSWSS.js} +1 -1
- package/dist/{chunk-D33YTSX5.js → chunk-DSID757X.js} +5 -4
- package/dist/{chunk-OXUY2A6L.js → chunk-EGUQLBHE.js} +22 -8
- package/dist/{chunk-2INLLLMZ.js → chunk-EXXSN3BW.js} +202 -26
- package/dist/{chunk-HURREPU2.js → chunk-FC6KCJSA.js} +87 -150
- package/dist/{chunk-HYXDKS4N.js → chunk-GSGNX35Q.js} +5 -5
- package/dist/{chunk-7GQCWFOE.js → chunk-J3YQ457H.js} +171 -85
- package/dist/{chunk-ORMZXBKQ.js → chunk-JUTFX2RM.js} +18 -10
- package/dist/{chunk-QE4TTDU3.js → chunk-KJ3UKABJ.js} +12 -11
- package/dist/{chunk-XRRZKZYX.js → chunk-LI4W3U6C.js} +1 -1
- package/dist/{chunk-47M47FOM.js → chunk-O6TRVMJI.js} +58 -6
- package/dist/{chunk-JSXPZCET.js → chunk-Q5J2LVKH.js} +1 -1
- package/dist/{chunk-5MT6SJ3P.js → chunk-QGMSESDD.js} +10 -5
- package/dist/{chunk-AIF3Z2T7.js → chunk-RGLPEBDE.js} +13 -10
- package/dist/{chunk-5Q4R7HCL.js → chunk-TQQUN4WR.js} +11 -2
- package/dist/{chunk-PK6FK2G2.js → chunk-UCNP3HVM.js} +183 -30
- package/dist/{chunk-XC4MEKGA.js → chunk-V3LHZSU5.js} +8 -2
- package/dist/{chunk-VVWPJ543.js → chunk-VWT3VXPL.js} +55 -20
- package/dist/{chunk-SXXVZMKZ.js → chunk-ZVLHNEEL.js} +17 -35
- package/dist/{contracts-DRIuclVT.d.cts → contracts-CLqzJnOV.d.ts} +28 -17
- package/dist/{contracts-DRIuclVT.d.ts → contracts-CTOJXu-x.d.cts} +28 -17
- package/dist/{customElement-MmInOW1U.d.ts → customElement-pYDKUzWl.d.cts} +11 -3
- package/dist/{customElement-MmInOW1U.d.cts → customElement-pYDKUzWl.d.ts} +11 -3
- package/dist/data.cjs +205 -39
- package/dist/data.d.cts +119 -3
- package/dist/data.d.ts +119 -3
- package/dist/data.js +6 -6
- package/dist/devtools.cjs +18 -5
- package/dist/devtools.js +5 -5
- package/dist/ecosystem.cjs +462 -58
- package/dist/ecosystem.d.cts +2 -1
- package/dist/ecosystem.d.ts +2 -1
- package/dist/ecosystem.js +9 -8
- package/dist/extras.cjs +852 -296
- package/dist/extras.d.cts +5 -4
- package/dist/extras.d.ts +5 -4
- package/dist/extras.js +24 -23
- package/dist/index.cjs +721 -176
- package/dist/index.d.cts +220 -169
- package/dist/index.d.ts +220 -169
- package/dist/index.js +16 -12
- package/dist/motion.cjs +12 -4
- package/dist/motion.js +3 -3
- package/dist/patterns.cjs +37 -21
- package/dist/patterns.d.cts +2 -1
- package/dist/patterns.d.ts +2 -1
- package/dist/patterns.js +6 -6
- package/dist/performance.cjs +48 -6
- package/dist/performance.d.cts +12 -2
- package/dist/performance.d.ts +12 -2
- package/dist/performance.js +8 -6
- package/dist/plugins.cjs +672 -261
- package/dist/plugins.d.cts +131 -13
- package/dist/plugins.d.ts +131 -13
- package/dist/plugins.js +83 -47
- package/dist/{ssr-XOTUASDO.js → ssr-5OWAH3U2.js} +4 -2
- package/dist/{ssr-Bli9XRW5.d.cts → ssr-C8hgIAw7.d.cts} +6 -0
- package/dist/{ssr-Bli9XRW5.d.ts → ssr-C8hgIAw7.d.ts} +6 -0
- package/dist/ssr.cjs +509 -142
- package/dist/ssr.d.cts +55 -5
- package/dist/ssr.d.ts +55 -5
- package/dist/ssr.js +11 -9
- package/dist/{tagFactory-DFstCLQV.d.cts → tagFactory-8qL9LCIx.d.cts} +58 -19
- package/dist/{tagFactory-DkaNVUNV.d.ts → tagFactory-BL2fymez.d.ts} +58 -19
- package/dist/testing.cjs +17 -4
- package/dist/testing.js +4 -4
- package/dist/types-CJFViL6Q.d.cts +26 -0
- package/dist/types-CJFViL6Q.d.ts +26 -0
- package/dist/ui.cjs +635 -254
- package/dist/ui.d.cts +3 -2
- package/dist/ui.d.ts +3 -2
- package/dist/ui.js +9 -8
- package/dist/widgets.cjs +22 -14
- package/dist/widgets.js +7 -7
- package/package.json +8 -5
package/dist/plugins.cjs
CHANGED
|
@@ -152,7 +152,7 @@ function stripControlChars(value) {
|
|
|
152
152
|
return value.replace(/[\x00-\x20\x7f-\x9f]+/g, "");
|
|
153
153
|
}
|
|
154
154
|
function canonicalAttrName(name) {
|
|
155
|
-
return name.replace(
|
|
155
|
+
return ASCII_UPPER.test(name) ? name.replace(ASCII_UPPER_G, (ch) => String.fromCharCode(ch.charCodeAt(0) + 32)) : name;
|
|
156
156
|
}
|
|
157
157
|
function isEventHandlerAttr(name) {
|
|
158
158
|
if (name.length < 3) return false;
|
|
@@ -163,6 +163,9 @@ function sanitizeUrl(url) {
|
|
|
163
163
|
const probe = stripControlChars(url).trim();
|
|
164
164
|
if (!probe) return "";
|
|
165
165
|
const output2 = url.replace(OUTER_TRIM, "");
|
|
166
|
+
if (probe.length >= 2 && (probe[0] === "\\" || probe[0] === "/") && (probe[1] === "\\" || probe[1] === "/") && (probe[0] === "\\" || probe[1] === "\\")) {
|
|
167
|
+
return "";
|
|
168
|
+
}
|
|
166
169
|
const lower = probe.toLowerCase();
|
|
167
170
|
let schemeEnd = -1;
|
|
168
171
|
for (let i2 = 0; i2 < lower.length; i2++) {
|
|
@@ -179,18 +182,57 @@ function sanitizeUrl(url) {
|
|
|
179
182
|
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
180
183
|
return output2;
|
|
181
184
|
}
|
|
185
|
+
function isSrcsetWhitespace(ch) {
|
|
186
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
187
|
+
}
|
|
182
188
|
function sanitizeSrcset(value) {
|
|
183
|
-
const
|
|
189
|
+
const input2 = String(value);
|
|
184
190
|
const out = [];
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
|
|
191
|
+
let i2 = 0;
|
|
192
|
+
const n = input2.length;
|
|
193
|
+
while (i2 < n) {
|
|
194
|
+
while (i2 < n && (isSrcsetWhitespace(input2[i2]) || input2[i2] === ",")) i2++;
|
|
195
|
+
if (i2 >= n) break;
|
|
196
|
+
const urlStart = i2;
|
|
197
|
+
while (i2 < n && !isSrcsetWhitespace(input2[i2])) i2++;
|
|
198
|
+
let url = input2.slice(urlStart, i2);
|
|
199
|
+
const descriptors = [];
|
|
200
|
+
if (url.endsWith(",")) {
|
|
201
|
+
url = url.replace(/,+$/, "");
|
|
202
|
+
} else {
|
|
203
|
+
let current = "";
|
|
204
|
+
let inParens = false;
|
|
205
|
+
while (i2 < n) {
|
|
206
|
+
const ch = input2[i2];
|
|
207
|
+
if (inParens) {
|
|
208
|
+
current += ch;
|
|
209
|
+
if (ch === ")") inParens = false;
|
|
210
|
+
i2++;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (isSrcsetWhitespace(ch)) {
|
|
214
|
+
if (current) descriptors.push(current);
|
|
215
|
+
current = "";
|
|
216
|
+
i2++;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (ch === ",") {
|
|
220
|
+
i2++;
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
if (ch === "(") inParens = true;
|
|
224
|
+
current += ch;
|
|
225
|
+
i2++;
|
|
226
|
+
}
|
|
227
|
+
if (current) descriptors.push(current);
|
|
228
|
+
}
|
|
229
|
+
if (url === "") continue;
|
|
230
|
+
if (descriptors.length > 1) continue;
|
|
231
|
+
if (descriptors.length === 1 && !SRCSET_DESCRIPTOR.test(descriptors[0])) continue;
|
|
232
|
+
const safe = sanitizeUrl(url);
|
|
192
233
|
if (!safe) continue;
|
|
193
|
-
|
|
234
|
+
if (safe.startsWith(",") || safe.endsWith(",")) continue;
|
|
235
|
+
out.push(descriptors.length === 1 ? `${safe} ${descriptors[0]}` : safe);
|
|
194
236
|
}
|
|
195
237
|
return out.join(", ");
|
|
196
238
|
}
|
|
@@ -259,7 +301,9 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
259
301
|
"behavior: loads and runs a remote HTC script",
|
|
260
302
|
"@import pulls in a remote stylesheet",
|
|
261
303
|
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
262
|
-
"filter:progid activates legacy scriptable filters"
|
|
304
|
+
"filter:progid activates legacy scriptable filters",
|
|
305
|
+
"image() fetches its string argument as a URL, the same exfiltration channel as url()",
|
|
306
|
+
"src() fetches its string argument as a URL, the same exfiltration channel as url()"
|
|
263
307
|
];
|
|
264
308
|
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
265
309
|
const where = describeElement(ctx?.element);
|
|
@@ -274,27 +318,110 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
274
318
|
return `style declaration "${declaration}" was dropped by the style sanitizer on ${where} \u2014 ${reasons[reason]}. The element renders without it, which usually looks like a missing image rather than an error. Sanctioned alternatives: for a content image use an <img> element (or a <picture>); for decoration, put the rule in a stylesheet and set a class instead \u2014 stylesheet CSS is not sanitized, only inline style attributes are. If this declaration is not yours, it came from untrusted data and the drop just prevented an exfiltration.`;
|
|
275
319
|
});
|
|
276
320
|
}
|
|
321
|
+
function normalizeCssForScan(value) {
|
|
322
|
+
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
323
|
+
return normalized.toLowerCase().replace(/\s+/g, "");
|
|
324
|
+
}
|
|
277
325
|
function blockedCssReason(value) {
|
|
278
326
|
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
279
|
-
const
|
|
280
|
-
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
327
|
+
const lower = normalizeCssForScan(value);
|
|
281
328
|
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
282
329
|
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
283
330
|
}
|
|
284
331
|
return -1;
|
|
285
332
|
}
|
|
286
|
-
function
|
|
287
|
-
const reason =
|
|
333
|
+
function sanitizeCSSDeclaration(property, value, context) {
|
|
334
|
+
const reason = blockedDeclarationReason(property, value);
|
|
288
335
|
if (reason === -1) return value;
|
|
289
|
-
warnDroppedDeclaration(value, reason, context);
|
|
336
|
+
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
290
337
|
return "";
|
|
291
338
|
}
|
|
339
|
+
function blockedDeclarationReason(property, value) {
|
|
340
|
+
const reason = blockedCssReason(value);
|
|
341
|
+
if (reason !== -1) return reason;
|
|
342
|
+
const name = canonicalAttrName(property);
|
|
343
|
+
if (name === "behavior") return CSS_REASON_BEHAVIOR;
|
|
344
|
+
if (name === "-moz-binding") return CSS_REASON_MOZ_BINDING;
|
|
345
|
+
if ((name === "filter" || name === "-ms-filter") && normalizeCssForScan(value).includes("progid:")) {
|
|
346
|
+
return CSS_REASON_PROGID;
|
|
347
|
+
}
|
|
348
|
+
return -1;
|
|
349
|
+
}
|
|
350
|
+
function parseStyleDeclarations(css) {
|
|
351
|
+
const chunks = [];
|
|
352
|
+
let buf = "";
|
|
353
|
+
let depth = 0;
|
|
354
|
+
let quote2 = "";
|
|
355
|
+
for (let i2 = 0; i2 < css.length; i2++) {
|
|
356
|
+
const ch = css[i2];
|
|
357
|
+
if (quote2) {
|
|
358
|
+
buf += ch;
|
|
359
|
+
if (ch === "\\" && i2 + 1 < css.length) buf += css[++i2];
|
|
360
|
+
else if (ch === quote2) quote2 = "";
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (ch === "\\") {
|
|
364
|
+
buf += ch;
|
|
365
|
+
if (i2 + 1 < css.length) buf += css[++i2];
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
if (ch === "/" && css[i2 + 1] === "*") {
|
|
369
|
+
const end = css.indexOf("*/", i2 + 2);
|
|
370
|
+
if (end === -1) return null;
|
|
371
|
+
i2 = end + 1;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
if (ch === '"' || ch === "'") quote2 = ch;
|
|
375
|
+
else if (ch === "(" || ch === "[") depth++;
|
|
376
|
+
else if (ch === ")" || ch === "]") {
|
|
377
|
+
if (--depth < 0) return null;
|
|
378
|
+
} else if (ch === "{" || ch === "}") return null;
|
|
379
|
+
else if (ch === ";" && depth === 0) {
|
|
380
|
+
chunks.push(buf);
|
|
381
|
+
buf = "";
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
buf += ch;
|
|
385
|
+
}
|
|
386
|
+
if (quote2 || depth !== 0) return null;
|
|
387
|
+
chunks.push(buf);
|
|
388
|
+
const out = [];
|
|
389
|
+
for (const chunk of chunks) {
|
|
390
|
+
const colon = chunk.indexOf(":");
|
|
391
|
+
if (colon === -1) continue;
|
|
392
|
+
const rawName = chunk.slice(0, colon).trim();
|
|
393
|
+
if (!/^(--[\w-]+|-?[a-zA-Z_][\w-]*)$/.test(rawName)) continue;
|
|
394
|
+
let value = chunk.slice(colon + 1).trim();
|
|
395
|
+
const bang = /!\s*important\s*$/i.exec(value);
|
|
396
|
+
if (bang) value = value.slice(0, bang.index).trim();
|
|
397
|
+
if (value === "") continue;
|
|
398
|
+
const property = rawName.startsWith("--") ? rawName : canonicalAttrName(rawName);
|
|
399
|
+
out.push([property, value, bang !== null]);
|
|
400
|
+
}
|
|
401
|
+
return out;
|
|
402
|
+
}
|
|
403
|
+
function sanitizeStyleDeclarationList(cssText, context) {
|
|
404
|
+
const input2 = String(cssText);
|
|
405
|
+
const declarations = parseStyleDeclarations(input2);
|
|
406
|
+
if (declarations === null) {
|
|
407
|
+
if (blockedCssReason(input2) !== -1) warnDroppedDeclaration(input2, blockedCssReason(input2), context);
|
|
408
|
+
return "";
|
|
409
|
+
}
|
|
410
|
+
const kept = [];
|
|
411
|
+
for (const [property, value, important] of declarations) {
|
|
412
|
+
const reason = blockedDeclarationReason(property, value);
|
|
413
|
+
if (reason !== -1) {
|
|
414
|
+
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
kept.push(`${property}: ${value}${important ? " !important" : ""}`);
|
|
418
|
+
}
|
|
419
|
+
return kept.join("; ");
|
|
420
|
+
}
|
|
292
421
|
function sanitizeStyleAttribute(cssText, context) {
|
|
293
422
|
const input2 = String(cssText);
|
|
294
423
|
if (input2.trim() === "") return "";
|
|
295
|
-
if (typeof document === "undefined")
|
|
296
|
-
return sanitizeCSSValue(input2, context) === "" ? "" : input2;
|
|
297
|
-
}
|
|
424
|
+
if (typeof document === "undefined") return sanitizeStyleDeclarationList(input2, context);
|
|
298
425
|
const probe = document.createElement("div");
|
|
299
426
|
try {
|
|
300
427
|
probe.style.cssText = input2;
|
|
@@ -305,8 +432,7 @@ function sanitizeStyleAttribute(cssText, context) {
|
|
|
305
432
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
306
433
|
const property = probe.style[i2];
|
|
307
434
|
const value = probe.style.getPropertyValue(property);
|
|
308
|
-
|
|
309
|
-
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
435
|
+
const reason = blockedDeclarationReason(property, value);
|
|
310
436
|
if (reason !== -1) {
|
|
311
437
|
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
312
438
|
continue;
|
|
@@ -333,14 +459,21 @@ function sanitizeAttributeString(attr, value, context) {
|
|
|
333
459
|
if (lower === "style") return sanitizeStyleAttribute(value, context);
|
|
334
460
|
return value;
|
|
335
461
|
}
|
|
336
|
-
|
|
462
|
+
function resolveAttributeValue(attr, value, context) {
|
|
463
|
+
if (!isPolicyAttribute(attr)) return value;
|
|
464
|
+
const safe = sanitizeAttributeString(attr, value, context);
|
|
465
|
+
return safe === "" ? null : safe;
|
|
466
|
+
}
|
|
467
|
+
var ASCII_UPPER, ASCII_UPPER_G, SAFE_URL_PROTOCOLS, OUTER_TRIM, SRCSET_DESCRIPTOR, CSS_DANGER_GATE, BLOCKED_CSS_NEEDLES, CSS_REASON_MOZ_BINDING, CSS_REASON_BEHAVIOR, CSS_REASON_PROGID, warnedDeclarations, MAX_WARNED_DECLARATIONS, declarationCapAnnounced, URL_ATTRIBUTES, HTML_CONTENT_ATTRIBUTES;
|
|
337
468
|
var init_sanitize = __esm({
|
|
338
469
|
"src/utils/sanitize.ts"() {
|
|
339
470
|
"use strict";
|
|
340
471
|
init_dev();
|
|
472
|
+
ASCII_UPPER = /[A-Z]/;
|
|
473
|
+
ASCII_UPPER_G = /[A-Z]/g;
|
|
341
474
|
SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
|
|
342
475
|
OUTER_TRIM = /^[\x00-\x20\x7f-\x9f]+|[\x00-\x20\x7f-\x9f]+$/g;
|
|
343
|
-
SRCSET_DESCRIPTOR = /^\
|
|
476
|
+
SRCSET_DESCRIPTOR = /^\d+(\.\d+)?[wx]$/;
|
|
344
477
|
CSS_DANGER_GATE = /[(:@\\]/;
|
|
345
478
|
BLOCKED_CSS_NEEDLES = [
|
|
346
479
|
"url(",
|
|
@@ -351,8 +484,16 @@ var init_sanitize = __esm({
|
|
|
351
484
|
"behavior:",
|
|
352
485
|
"@import",
|
|
353
486
|
"image-set(",
|
|
354
|
-
"filter:progid"
|
|
487
|
+
"filter:progid",
|
|
488
|
+
// CSS Images 4 `image("…")` and CSS Values 5 `src("…")` take a URL as a
|
|
489
|
+
// plain STRING, so they fetch without ever spelling `url(`. Support is thin
|
|
490
|
+
// today, which is exactly when a blocklist should get ahead of it.
|
|
491
|
+
"image(",
|
|
492
|
+
"src("
|
|
355
493
|
];
|
|
494
|
+
CSS_REASON_MOZ_BINDING = 4;
|
|
495
|
+
CSS_REASON_BEHAVIOR = 5;
|
|
496
|
+
CSS_REASON_PROGID = 8;
|
|
356
497
|
warnedDeclarations = /* @__PURE__ */ new Set();
|
|
357
498
|
MAX_WARNED_DECLARATIONS = 100;
|
|
358
499
|
declarationCapAnnounced = false;
|
|
@@ -378,6 +519,224 @@ var init_sanitize = __esm({
|
|
|
378
519
|
}
|
|
379
520
|
});
|
|
380
521
|
|
|
522
|
+
// src/utils/metaRefresh.ts
|
|
523
|
+
function isAsciiWhitespace(ch) {
|
|
524
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
525
|
+
}
|
|
526
|
+
function trimAsciiWhitespace(value) {
|
|
527
|
+
let start = 0;
|
|
528
|
+
let end = value.length;
|
|
529
|
+
while (start < end && isAsciiWhitespace(value[start])) start++;
|
|
530
|
+
while (end > start && isAsciiWhitespace(value[end - 1])) end--;
|
|
531
|
+
return value.slice(start, end);
|
|
532
|
+
}
|
|
533
|
+
function parseMetaRefreshContent(content) {
|
|
534
|
+
const raw = trimAsciiWhitespace(stripControlChars(content));
|
|
535
|
+
if (raw === "") return forbidden(DEV ? "empty content" : "");
|
|
536
|
+
let i2 = 0;
|
|
537
|
+
while (i2 < raw.length && raw[i2] >= "0" && raw[i2] <= "9") i2++;
|
|
538
|
+
if (i2 === 0) return forbidden(DEV ? "missing or non-numeric delay" : "");
|
|
539
|
+
const delay = Number.parseInt(raw.slice(0, i2), 10);
|
|
540
|
+
if (!Number.isFinite(delay)) return forbidden(DEV ? "unparseable delay" : "");
|
|
541
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
542
|
+
if (i2 === raw.length) return { kind: "delay-only", delay };
|
|
543
|
+
if (raw[i2] !== ";" && raw[i2] !== ",") return forbidden(DEV ? "unexpected text after delay" : "");
|
|
544
|
+
i2++;
|
|
545
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
546
|
+
const keyStart = i2;
|
|
547
|
+
while (i2 < raw.length && !isAsciiWhitespace(raw[i2]) && raw[i2] !== "=") i2++;
|
|
548
|
+
const key = raw.slice(keyStart, i2).toLowerCase();
|
|
549
|
+
if (key !== "url") return forbidden(DEV ? `unsupported refresh key ${JSON.stringify(key)}` : "");
|
|
550
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
551
|
+
if (raw[i2] !== "=") return forbidden(DEV ? "missing '=' after url" : "");
|
|
552
|
+
i2++;
|
|
553
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
554
|
+
let destination;
|
|
555
|
+
const quote2 = raw[i2];
|
|
556
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
557
|
+
const close = raw.indexOf(quote2, i2 + 1);
|
|
558
|
+
if (close === -1) return forbidden(DEV ? "unterminated quoted destination" : "");
|
|
559
|
+
destination = raw.slice(i2 + 1, close);
|
|
560
|
+
const rest = trimAsciiWhitespace(raw.slice(close + 1));
|
|
561
|
+
if (rest !== "") return forbidden(DEV ? "trailing text after quoted destination" : "");
|
|
562
|
+
} else {
|
|
563
|
+
destination = trimAsciiWhitespace(raw.slice(i2));
|
|
564
|
+
if (/[;,]/.test(destination)) return forbidden(DEV ? "multiple refresh assignments" : "");
|
|
565
|
+
}
|
|
566
|
+
if (destination === "") return forbidden(DEV ? "empty destination" : "");
|
|
567
|
+
const sanitizedDestination = sanitizeUrl(destination);
|
|
568
|
+
if (sanitizedDestination === "") return forbidden(DEV ? "destination uses a disallowed protocol" : "");
|
|
569
|
+
return { kind: "allowed", delay, destination, sanitizedDestination };
|
|
570
|
+
}
|
|
571
|
+
function resolveMetaRefreshPolicy(attributes) {
|
|
572
|
+
let httpEquiv;
|
|
573
|
+
let content;
|
|
574
|
+
let duplicateName;
|
|
575
|
+
const seen = /* @__PURE__ */ new Set();
|
|
576
|
+
for (const [key, value] of attributes) {
|
|
577
|
+
const canonical = canonicalAttrName(key);
|
|
578
|
+
if (seen.has(canonical)) duplicateName = canonical;
|
|
579
|
+
seen.add(canonical);
|
|
580
|
+
if (canonical === "http-equiv") httpEquiv = value;
|
|
581
|
+
else if (canonical === "content") content = value;
|
|
582
|
+
}
|
|
583
|
+
if (duplicateName !== void 0) {
|
|
584
|
+
return forbidden(DEV ? `duplicate case-insensitive attribute ${JSON.stringify(duplicateName)}` : "");
|
|
585
|
+
}
|
|
586
|
+
if (typeof httpEquiv !== "string") return { kind: "not-refresh" };
|
|
587
|
+
if (trimAsciiWhitespace(stripControlChars(httpEquiv)).toLowerCase() !== "refresh") {
|
|
588
|
+
return { kind: "not-refresh" };
|
|
589
|
+
}
|
|
590
|
+
if (typeof content !== "string") return { kind: "not-refresh" };
|
|
591
|
+
return parseMetaRefreshContent(content);
|
|
592
|
+
}
|
|
593
|
+
function normalizeMetaAttributes(props) {
|
|
594
|
+
const out = /* @__PURE__ */ new Map();
|
|
595
|
+
const seen = /* @__PURE__ */ new Set();
|
|
596
|
+
for (const key of Object.keys(props)) {
|
|
597
|
+
const canonical = canonicalAttrName(key);
|
|
598
|
+
if (seen.has(canonical)) return null;
|
|
599
|
+
seen.add(canonical);
|
|
600
|
+
out.set(key, props[key]);
|
|
601
|
+
}
|
|
602
|
+
return out;
|
|
603
|
+
}
|
|
604
|
+
function isForbiddenMetaEntry(props) {
|
|
605
|
+
const normalized = normalizeMetaAttributes(props);
|
|
606
|
+
if (normalized === null) return true;
|
|
607
|
+
return resolveMetaRefreshPolicy(normalized).kind === "forbidden";
|
|
608
|
+
}
|
|
609
|
+
var forbidden;
|
|
610
|
+
var init_metaRefresh = __esm({
|
|
611
|
+
"src/utils/metaRefresh.ts"() {
|
|
612
|
+
"use strict";
|
|
613
|
+
init_dev();
|
|
614
|
+
init_sanitize();
|
|
615
|
+
forbidden = (reason) => ({ kind: "forbidden", reason });
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
// src/utils/elementPolicy.ts
|
|
620
|
+
function canonicalTagName(tag) {
|
|
621
|
+
return canonicalAttrName(tag);
|
|
622
|
+
}
|
|
623
|
+
function isBlockedElement(tag) {
|
|
624
|
+
return BLOCKED_ELEMENTS.has(canonicalTagName(tag));
|
|
625
|
+
}
|
|
626
|
+
function isCodeTextElement(tag) {
|
|
627
|
+
return CODE_TEXT_ELEMENTS.has(canonicalTagName(tag));
|
|
628
|
+
}
|
|
629
|
+
function isHtmlNamespace(el) {
|
|
630
|
+
return el.namespaceURI === HTML_NS || el.namespaceURI === null;
|
|
631
|
+
}
|
|
632
|
+
function metaSnapshot(el, canonical, value) {
|
|
633
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
634
|
+
const attrs = el.attributes;
|
|
635
|
+
for (let i2 = 0; i2 < attrs.length; i2++) {
|
|
636
|
+
const attr = attrs[i2];
|
|
637
|
+
if (attr.name === canonical) continue;
|
|
638
|
+
snapshot.set(attr.name, attr.value);
|
|
639
|
+
}
|
|
640
|
+
if (canonical !== null && value !== null) snapshot.set(canonical, value);
|
|
641
|
+
return snapshot;
|
|
642
|
+
}
|
|
643
|
+
function claimReactiveMeta(el) {
|
|
644
|
+
if (reactiveMetaElements.has(el)) return;
|
|
645
|
+
reactiveMetaElements.add(el);
|
|
646
|
+
if (el.getAttribute("content") === null) return;
|
|
647
|
+
if (resolveMetaRefreshPolicy(metaSnapshot(el, null, null)).kind !== "not-refresh") {
|
|
648
|
+
el.removeAttribute("content");
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
function metaRefusal(el, name, value, origin) {
|
|
652
|
+
if (!isHtmlNamespace(el)) return ContextualRefusal.None;
|
|
653
|
+
const canonical = canonicalAttrName(name);
|
|
654
|
+
if (canonical !== "http-equiv" && canonical !== "content") return ContextualRefusal.None;
|
|
655
|
+
if (origin === "reactive") claimReactiveMeta(el);
|
|
656
|
+
if (value === null) return ContextualRefusal.None;
|
|
657
|
+
if (canonical === "content" && !el.hasAttribute("http-equiv")) return ContextualRefusal.None;
|
|
658
|
+
const decision = resolveMetaRefreshPolicy(metaSnapshot(el, canonical, value));
|
|
659
|
+
if (decision.kind === "forbidden") return ContextualRefusal.MetaRefreshForbidden;
|
|
660
|
+
if (decision.kind !== "not-refresh" && reactiveMetaElements.has(el)) return ContextualRefusal.MetaRefreshReactive;
|
|
661
|
+
return ContextualRefusal.None;
|
|
662
|
+
}
|
|
663
|
+
function animationRefusal(name, value) {
|
|
664
|
+
if (value === null || canonicalAttrName(name) !== "attributename") return ContextualRefusal.None;
|
|
665
|
+
const target = stripControlChars(value);
|
|
666
|
+
return isUrlAttribute(target) || isEventHandlerAttr(target) || isHtmlContentAttribute(target) ? ContextualRefusal.AnimationTarget : ContextualRefusal.None;
|
|
667
|
+
}
|
|
668
|
+
function relHasStylesheet(rel) {
|
|
669
|
+
if (rel === null) return false;
|
|
670
|
+
const lower = canonicalAttrName(rel);
|
|
671
|
+
if (!lower.includes("stylesheet")) return false;
|
|
672
|
+
const tokens = lower.split(/[\t\n\f\r ]+/);
|
|
673
|
+
for (let i2 = 0; i2 < tokens.length; i2++) if (tokens[i2] === "stylesheet") return true;
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
676
|
+
function stylesheetRefusal(el, name, value, origin) {
|
|
677
|
+
if (!isHtmlNamespace(el)) return ContextualRefusal.None;
|
|
678
|
+
const canonical = canonicalAttrName(name);
|
|
679
|
+
if (canonical === "href") {
|
|
680
|
+
if (origin === "static" || value === null) return ContextualRefusal.None;
|
|
681
|
+
if (relHasStylesheet(el.getAttribute("rel"))) return ContextualRefusal.StylesheetSource;
|
|
682
|
+
runtimeHrefLinks.add(el);
|
|
683
|
+
return ContextualRefusal.None;
|
|
684
|
+
}
|
|
685
|
+
if (canonical === "rel") {
|
|
686
|
+
if (!relHasStylesheet(value)) return ContextualRefusal.None;
|
|
687
|
+
return runtimeHrefLinks.has(el) && el.hasAttribute("href") ? ContextualRefusal.StylesheetSource : ContextualRefusal.None;
|
|
688
|
+
}
|
|
689
|
+
return ContextualRefusal.None;
|
|
690
|
+
}
|
|
691
|
+
function contextualAttributeRefusal(el, name, value, origin) {
|
|
692
|
+
const local = el.localName;
|
|
693
|
+
if (local === "meta") return metaRefusal(el, name, value, origin);
|
|
694
|
+
if (local === "link") return stylesheetRefusal(el, name, value, origin);
|
|
695
|
+
if (local === "script") {
|
|
696
|
+
if (origin === "static" || value === null) return ContextualRefusal.None;
|
|
697
|
+
return SCRIPT_SOURCE_ATTRIBUTES.has(canonicalAttrName(name)) ? ContextualRefusal.ScriptSource : ContextualRefusal.None;
|
|
698
|
+
}
|
|
699
|
+
if (SVG_ANIMATION_ELEMENTS.has(local) && el.namespaceURI === SVG_NS) return animationRefusal(name, value);
|
|
700
|
+
return ContextualRefusal.None;
|
|
701
|
+
}
|
|
702
|
+
function settleAttributeProvenance(el, name, origin) {
|
|
703
|
+
if (el.localName !== "link" || canonicalAttrName(name) !== "href") return;
|
|
704
|
+
if (origin !== "static" && el.hasAttribute("href")) runtimeHrefLinks.add(el);
|
|
705
|
+
else runtimeHrefLinks.delete(el);
|
|
706
|
+
}
|
|
707
|
+
function isForbiddenMetaSnapshot(attributes) {
|
|
708
|
+
return resolveMetaRefreshPolicy(attributes).kind === "forbidden";
|
|
709
|
+
}
|
|
710
|
+
var HTML_NS, SVG_NS, BLOCKED_ELEMENTS, CODE_TEXT_ELEMENTS, ContextualRefusal, SCRIPT_SOURCE_ATTRIBUTES, SVG_ANIMATION_ELEMENTS, reactiveMetaElements, runtimeHrefLinks;
|
|
711
|
+
var init_elementPolicy = __esm({
|
|
712
|
+
"src/utils/elementPolicy.ts"() {
|
|
713
|
+
"use strict";
|
|
714
|
+
init_metaRefresh();
|
|
715
|
+
init_sanitize();
|
|
716
|
+
HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
717
|
+
SVG_NS = "http://www.w3.org/2000/svg";
|
|
718
|
+
BLOCKED_ELEMENTS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
719
|
+
CODE_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
720
|
+
ContextualRefusal = {
|
|
721
|
+
None: 0,
|
|
722
|
+
/** The element would carry a refresh directive the shared policy forbids. */
|
|
723
|
+
MetaRefreshForbidden: 1,
|
|
724
|
+
/** A `<meta>` with a reactive binding may not carry any refresh directive. */
|
|
725
|
+
MetaRefreshReactive: 2,
|
|
726
|
+
/** A runtime value may not choose which program a `<script>` runs. */
|
|
727
|
+
ScriptSource: 3,
|
|
728
|
+
/** An SVG animation may not target a URL, handler or document attribute. */
|
|
729
|
+
AnimationTarget: 4,
|
|
730
|
+
/** A runtime-written `href` may not become an applied stylesheet. */
|
|
731
|
+
StylesheetSource: 5
|
|
732
|
+
};
|
|
733
|
+
SCRIPT_SOURCE_ATTRIBUTES = /* @__PURE__ */ new Set(["src", "href", "xlink:href", "type", "language"]);
|
|
734
|
+
SVG_ANIMATION_ELEMENTS = /* @__PURE__ */ new Set(["animate", "set", "animateMotion", "animateTransform", "animateColor"]);
|
|
735
|
+
reactiveMetaElements = /* @__PURE__ */ new WeakSet();
|
|
736
|
+
runtimeHrefLinks = /* @__PURE__ */ new WeakSet();
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
|
|
381
740
|
// src/core/rendering/dispose.ts
|
|
382
741
|
var dispose_exports = {};
|
|
383
742
|
__export(dispose_exports, {
|
|
@@ -607,99 +966,22 @@ var init_ssr_context = __esm({
|
|
|
607
966
|
}
|
|
608
967
|
});
|
|
609
968
|
|
|
610
|
-
// src/utils/
|
|
611
|
-
function
|
|
612
|
-
return
|
|
613
|
-
}
|
|
614
|
-
function trimAsciiWhitespace(value) {
|
|
615
|
-
let start = 0;
|
|
616
|
-
let end = value.length;
|
|
617
|
-
while (start < end && isAsciiWhitespace(value[start])) start++;
|
|
618
|
-
while (end > start && isAsciiWhitespace(value[end - 1])) end--;
|
|
619
|
-
return value.slice(start, end);
|
|
620
|
-
}
|
|
621
|
-
function parseMetaRefreshContent(content) {
|
|
622
|
-
const raw = trimAsciiWhitespace(stripControlChars(content));
|
|
623
|
-
if (raw === "") return forbidden("empty content");
|
|
624
|
-
let i2 = 0;
|
|
625
|
-
while (i2 < raw.length && raw[i2] >= "0" && raw[i2] <= "9") i2++;
|
|
626
|
-
if (i2 === 0) return forbidden("missing or non-numeric delay");
|
|
627
|
-
const delay = Number.parseInt(raw.slice(0, i2), 10);
|
|
628
|
-
if (!Number.isFinite(delay)) return forbidden("unparseable delay");
|
|
629
|
-
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
630
|
-
if (i2 === raw.length) return { kind: "delay-only", delay };
|
|
631
|
-
if (raw[i2] !== ";" && raw[i2] !== ",") return forbidden("unexpected text after delay");
|
|
632
|
-
i2++;
|
|
633
|
-
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
634
|
-
const keyStart = i2;
|
|
635
|
-
while (i2 < raw.length && !isAsciiWhitespace(raw[i2]) && raw[i2] !== "=") i2++;
|
|
636
|
-
const key = raw.slice(keyStart, i2).toLowerCase();
|
|
637
|
-
if (key !== "url") return forbidden(`unsupported refresh key ${JSON.stringify(key)}`);
|
|
638
|
-
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
639
|
-
if (raw[i2] !== "=") return forbidden("missing '=' after url");
|
|
640
|
-
i2++;
|
|
641
|
-
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
642
|
-
let destination;
|
|
643
|
-
const quote2 = raw[i2];
|
|
644
|
-
if (quote2 === '"' || quote2 === "'") {
|
|
645
|
-
const close = raw.indexOf(quote2, i2 + 1);
|
|
646
|
-
if (close === -1) return forbidden("unterminated quoted destination");
|
|
647
|
-
destination = raw.slice(i2 + 1, close);
|
|
648
|
-
const rest = trimAsciiWhitespace(raw.slice(close + 1));
|
|
649
|
-
if (rest !== "") return forbidden("trailing text after quoted destination");
|
|
650
|
-
} else {
|
|
651
|
-
destination = trimAsciiWhitespace(raw.slice(i2));
|
|
652
|
-
if (/[;,]/.test(destination)) return forbidden("multiple refresh assignments");
|
|
653
|
-
}
|
|
654
|
-
if (destination === "") return forbidden("empty destination");
|
|
655
|
-
const sanitizedDestination = sanitizeUrl(destination);
|
|
656
|
-
if (sanitizedDestination === "") return forbidden("destination uses a disallowed protocol");
|
|
657
|
-
return { kind: "allowed", delay, destination, sanitizedDestination };
|
|
658
|
-
}
|
|
659
|
-
function resolveMetaRefreshPolicy(attributes) {
|
|
660
|
-
let httpEquiv;
|
|
661
|
-
let content;
|
|
662
|
-
let duplicateName;
|
|
663
|
-
const seen = /* @__PURE__ */ new Set();
|
|
664
|
-
for (const [key, value] of attributes) {
|
|
665
|
-
const canonical = canonicalAttrName(key);
|
|
666
|
-
if (seen.has(canonical)) duplicateName = canonical;
|
|
667
|
-
seen.add(canonical);
|
|
668
|
-
if (canonical === "http-equiv") httpEquiv = value;
|
|
669
|
-
else if (canonical === "content") content = value;
|
|
670
|
-
}
|
|
671
|
-
if (duplicateName !== void 0) {
|
|
672
|
-
return forbidden(`duplicate case-insensitive attribute ${JSON.stringify(duplicateName)}`);
|
|
673
|
-
}
|
|
674
|
-
if (typeof httpEquiv !== "string") return { kind: "not-refresh" };
|
|
675
|
-
if (trimAsciiWhitespace(stripControlChars(httpEquiv)).toLowerCase() !== "refresh") {
|
|
676
|
-
return { kind: "not-refresh" };
|
|
677
|
-
}
|
|
678
|
-
if (typeof content !== "string") return { kind: "not-refresh" };
|
|
679
|
-
return parseMetaRefreshContent(content);
|
|
680
|
-
}
|
|
681
|
-
function normalizeMetaAttributes(props) {
|
|
682
|
-
const out = /* @__PURE__ */ new Map();
|
|
683
|
-
const seen = /* @__PURE__ */ new Set();
|
|
684
|
-
for (const key of Object.keys(props)) {
|
|
685
|
-
const canonical = canonicalAttrName(key);
|
|
686
|
-
if (seen.has(canonical)) return null;
|
|
687
|
-
seen.add(canonical);
|
|
688
|
-
out.set(key, props[key]);
|
|
689
|
-
}
|
|
690
|
-
return out;
|
|
969
|
+
// src/utils/guards.ts
|
|
970
|
+
function isUnsafeKey(key) {
|
|
971
|
+
return UNSAFE_KEYS.has(key);
|
|
691
972
|
}
|
|
692
|
-
function
|
|
693
|
-
|
|
694
|
-
if (
|
|
695
|
-
|
|
973
|
+
function readOwnGlobal(key) {
|
|
974
|
+
if (typeof window === "undefined") return void 0;
|
|
975
|
+
if (!Object.hasOwn(window, key)) return void 0;
|
|
976
|
+
const value = window[key];
|
|
977
|
+
if (typeof Node !== "undefined" && value instanceof Node) return void 0;
|
|
978
|
+
return value;
|
|
696
979
|
}
|
|
697
|
-
var
|
|
698
|
-
var
|
|
699
|
-
"src/utils/
|
|
980
|
+
var UNSAFE_KEYS;
|
|
981
|
+
var init_guards = __esm({
|
|
982
|
+
"src/utils/guards.ts"() {
|
|
700
983
|
"use strict";
|
|
701
|
-
|
|
702
|
-
forbidden = (reason) => ({ kind: "forbidden", reason });
|
|
984
|
+
UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
703
985
|
}
|
|
704
986
|
});
|
|
705
987
|
|
|
@@ -712,9 +994,7 @@ function isEmittableHeadAttrName(name) {
|
|
|
712
994
|
return true;
|
|
713
995
|
}
|
|
714
996
|
function sanitizeHeadAttrValue(canonical, value) {
|
|
715
|
-
|
|
716
|
-
const safe = sanitizeAttributeString(canonical, value);
|
|
717
|
-
return safe === "" ? null : safe;
|
|
997
|
+
return resolveAttributeValue(canonical, value);
|
|
718
998
|
}
|
|
719
999
|
function findDuplicateAttributeName(names) {
|
|
720
1000
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -801,15 +1081,9 @@ __export(ssr_exports, {
|
|
|
801
1081
|
suspenseSwapScript: () => suspenseSwapScript,
|
|
802
1082
|
trustHTML: () => trustHTML
|
|
803
1083
|
});
|
|
804
|
-
function isPolicyAttr(lowerName) {
|
|
805
|
-
return isPolicyAttribute(lowerName);
|
|
806
|
-
}
|
|
807
1084
|
function isForbiddenSsrAttr(lowerName) {
|
|
808
1085
|
return isHtmlContentAttribute(lowerName);
|
|
809
1086
|
}
|
|
810
|
-
function sanitizeSsrAttributeValue(lowerName, value) {
|
|
811
|
-
return sanitizeAttributeString(lowerName, value);
|
|
812
|
-
}
|
|
813
1087
|
function isSafeAttrName(name) {
|
|
814
1088
|
return SAFE_ATTR_NAME.test(name);
|
|
815
1089
|
}
|
|
@@ -823,6 +1097,63 @@ function ssrErrorComment(err) {
|
|
|
823
1097
|
function safeCommentText(text2) {
|
|
824
1098
|
return text2.replace(/-->/g, "-->").replace(/--!>/g, "--!>").replace(/<!--/g, "<!--").replace(/--$/g, "---");
|
|
825
1099
|
}
|
|
1100
|
+
function findNativeGetter(proto, name) {
|
|
1101
|
+
for (let p2 = proto; p2; p2 = Object.getPrototypeOf(p2)) {
|
|
1102
|
+
const get = Object.getOwnPropertyDescriptor(p2, name)?.get;
|
|
1103
|
+
if (get) return get;
|
|
1104
|
+
}
|
|
1105
|
+
return null;
|
|
1106
|
+
}
|
|
1107
|
+
function nativeAccessors() {
|
|
1108
|
+
const realm = Element;
|
|
1109
|
+
let accessors = nativeAccessorsByRealm.get(realm);
|
|
1110
|
+
if (!accessors) {
|
|
1111
|
+
accessors = {
|
|
1112
|
+
attributes: findNativeGetter(Element.prototype, "attributes"),
|
|
1113
|
+
tagName: findNativeGetter(Element.prototype, "tagName"),
|
|
1114
|
+
childNodes: findNativeGetter(Node.prototype, "childNodes"),
|
|
1115
|
+
getAttribute: Element.prototype.getAttribute
|
|
1116
|
+
};
|
|
1117
|
+
nativeAccessorsByRealm.set(realm, accessors);
|
|
1118
|
+
}
|
|
1119
|
+
return accessors;
|
|
1120
|
+
}
|
|
1121
|
+
function attributesOf(el) {
|
|
1122
|
+
const get = nativeAccessors().attributes;
|
|
1123
|
+
return get ? get.call(el) : el.attributes;
|
|
1124
|
+
}
|
|
1125
|
+
function tagNameOf(el) {
|
|
1126
|
+
const get = nativeAccessors().tagName;
|
|
1127
|
+
return get ? get.call(el) : el.tagName;
|
|
1128
|
+
}
|
|
1129
|
+
function childNodesOf(node) {
|
|
1130
|
+
const get = nativeAccessors().childNodes;
|
|
1131
|
+
return get ? get.call(node) : node.childNodes;
|
|
1132
|
+
}
|
|
1133
|
+
function getAttributeOf(el, name) {
|
|
1134
|
+
return nativeAccessors().getAttribute.call(el, name);
|
|
1135
|
+
}
|
|
1136
|
+
function serializeOpenTag(element, tag) {
|
|
1137
|
+
let html2 = `<${tag}`;
|
|
1138
|
+
const meta2 = tag === "meta" ? /* @__PURE__ */ new Map() : null;
|
|
1139
|
+
const attrs = attributesOf(element);
|
|
1140
|
+
for (let i2 = 0; i2 < attrs.length; i2++) {
|
|
1141
|
+
const attr = attrs[i2];
|
|
1142
|
+
const rawName = attr.name;
|
|
1143
|
+
if (!isSafeAttrName(rawName)) continue;
|
|
1144
|
+
if (isEventHandlerAttr(rawName)) continue;
|
|
1145
|
+
if (isForbiddenSsrAttr(rawName)) continue;
|
|
1146
|
+
const value = resolveAttributeValue(rawName.toLowerCase(), attr.value);
|
|
1147
|
+
if (value === null) continue;
|
|
1148
|
+
meta2?.set(rawName, value);
|
|
1149
|
+
html2 += ` ${rawName}="${escapeAttr(value)}"`;
|
|
1150
|
+
}
|
|
1151
|
+
if (meta2 && isForbiddenMetaSnapshot(meta2)) return null;
|
|
1152
|
+
if (!getAttributeOf(element, "data-sibu-hydrate")) {
|
|
1153
|
+
html2 += ` data-sibu-ssr="true"`;
|
|
1154
|
+
}
|
|
1155
|
+
return html2;
|
|
1156
|
+
}
|
|
826
1157
|
function renderToString(element) {
|
|
827
1158
|
if (element instanceof DocumentFragment) {
|
|
828
1159
|
return Array.from(element.childNodes).map((child) => {
|
|
@@ -842,35 +1173,21 @@ function renderToString(element) {
|
|
|
842
1173
|
if (!(element instanceof HTMLElement)) {
|
|
843
1174
|
return escapeHtml(element.textContent || "");
|
|
844
1175
|
}
|
|
845
|
-
const tag = element.
|
|
846
|
-
if (tag
|
|
1176
|
+
const tag = tagNameOf(element).toLowerCase();
|
|
1177
|
+
if (isCodeTextElement(tag)) {
|
|
847
1178
|
return DEV ? `<!--ssr:${tag}-stripped-->` : "";
|
|
848
1179
|
}
|
|
849
1180
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
850
1181
|
return DEV ? "<!--ssr:invalid-tag-->" : "";
|
|
851
1182
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
if (!isSafeAttrName(rawName)) continue;
|
|
856
|
-
if (isEventHandlerAttr(rawName)) continue;
|
|
857
|
-
if (isForbiddenSsrAttr(rawName)) continue;
|
|
858
|
-
const lowerName = rawName.toLowerCase();
|
|
859
|
-
let value = attr.value;
|
|
860
|
-
if (isPolicyAttr(lowerName)) {
|
|
861
|
-
value = sanitizeSsrAttributeValue(lowerName, value);
|
|
862
|
-
if (!value) continue;
|
|
863
|
-
}
|
|
864
|
-
html2 += ` ${rawName}="${escapeAttr(value)}"`;
|
|
865
|
-
}
|
|
866
|
-
if (element.dataset && !element.dataset.sibuHydrate) {
|
|
867
|
-
html2 += ` data-sibu-ssr="true"`;
|
|
868
|
-
}
|
|
1183
|
+
const openTag = serializeOpenTag(element, tag);
|
|
1184
|
+
if (openTag === null) return DEV ? `<!--ssr:${tag}-stripped-->` : "";
|
|
1185
|
+
let html2 = openTag;
|
|
869
1186
|
if (VOID_ELEMENTS.has(tag)) {
|
|
870
1187
|
return `${html2} />`;
|
|
871
1188
|
}
|
|
872
1189
|
html2 += ">";
|
|
873
|
-
for (const child of Array.from(element
|
|
1190
|
+
for (const child of Array.from(childNodesOf(element))) {
|
|
874
1191
|
try {
|
|
875
1192
|
html2 += renderToString(child);
|
|
876
1193
|
} catch (err) {
|
|
@@ -1020,12 +1337,8 @@ function buildAttrString(attrs, { allowEventHandlers = false } = {}) {
|
|
|
1020
1337
|
if (!isSafeAttrName(rawKey)) continue;
|
|
1021
1338
|
if (!allowEventHandlers && isEventHandlerAttr(rawKey)) continue;
|
|
1022
1339
|
if (isForbiddenSsrAttr(rawKey)) continue;
|
|
1023
|
-
const
|
|
1024
|
-
|
|
1025
|
-
if (isPolicyAttr(lowerKey)) {
|
|
1026
|
-
value = sanitizeSsrAttributeValue(lowerKey, value);
|
|
1027
|
-
if (!value) continue;
|
|
1028
|
-
}
|
|
1340
|
+
const value = resolveAttributeValue(rawKey.toLowerCase(), String(attrs[rawKey]));
|
|
1341
|
+
if (value === null) continue;
|
|
1029
1342
|
out.push(`${rawKey}="${escapeAttr(value)}"`);
|
|
1030
1343
|
}
|
|
1031
1344
|
return out.join(" ");
|
|
@@ -1088,8 +1401,8 @@ async function* renderToStream(element) {
|
|
|
1088
1401
|
yield escapeHtml(element.textContent || "");
|
|
1089
1402
|
return;
|
|
1090
1403
|
}
|
|
1091
|
-
const tag = element.
|
|
1092
|
-
if (tag
|
|
1404
|
+
const tag = tagNameOf(element).toLowerCase();
|
|
1405
|
+
if (isCodeTextElement(tag)) {
|
|
1093
1406
|
if (DEV) yield `<!--ssr:${tag}-stripped-->`;
|
|
1094
1407
|
return;
|
|
1095
1408
|
}
|
|
@@ -1097,29 +1410,17 @@ async function* renderToStream(element) {
|
|
|
1097
1410
|
if (DEV) yield "<!--ssr:invalid-tag-->";
|
|
1098
1411
|
return;
|
|
1099
1412
|
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
if (isEventHandlerAttr(rawName)) continue;
|
|
1105
|
-
if (isForbiddenSsrAttr(rawName)) continue;
|
|
1106
|
-
const lowerName = rawName.toLowerCase();
|
|
1107
|
-
let value = attr.value;
|
|
1108
|
-
if (isPolicyAttr(lowerName)) {
|
|
1109
|
-
value = sanitizeSsrAttributeValue(lowerName, value);
|
|
1110
|
-
if (!value) continue;
|
|
1111
|
-
}
|
|
1112
|
-
openTag += ` ${rawName}="${escapeAttr(value)}"`;
|
|
1113
|
-
}
|
|
1114
|
-
if (element.dataset && !element.dataset.sibuHydrate) {
|
|
1115
|
-
openTag += ` data-sibu-ssr="true"`;
|
|
1413
|
+
const openTag = serializeOpenTag(element, tag);
|
|
1414
|
+
if (openTag === null) {
|
|
1415
|
+
if (DEV) yield `<!--ssr:${tag}-stripped-->`;
|
|
1416
|
+
return;
|
|
1116
1417
|
}
|
|
1117
1418
|
if (VOID_ELEMENTS.has(tag)) {
|
|
1118
1419
|
yield `${openTag} />`;
|
|
1119
1420
|
return;
|
|
1120
1421
|
}
|
|
1121
1422
|
yield `${openTag}>`;
|
|
1122
|
-
for (const child of Array.from(element
|
|
1423
|
+
for (const child of Array.from(childNodesOf(element))) {
|
|
1123
1424
|
try {
|
|
1124
1425
|
yield* renderToStream(child);
|
|
1125
1426
|
} catch (err) {
|
|
@@ -1300,8 +1601,7 @@ function deserializeState(validate) {
|
|
|
1300
1601
|
"[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
|
|
1301
1602
|
);
|
|
1302
1603
|
}
|
|
1303
|
-
const
|
|
1304
|
-
const raw = w[SSR_DATA_ATTR];
|
|
1604
|
+
const raw = readOwnGlobal(SSR_DATA_ATTR);
|
|
1305
1605
|
if (raw === void 0) return void 0;
|
|
1306
1606
|
if (validate && !validate(raw)) return void 0;
|
|
1307
1607
|
return raw;
|
|
@@ -1312,13 +1612,15 @@ function escapeHtml(str) {
|
|
|
1312
1612
|
function escapeAttr(str) {
|
|
1313
1613
|
return str.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
1314
1614
|
}
|
|
1315
|
-
var SAFE_ATTR_NAME, VOID_ELEMENTS, SAFE_ID, SAFE_SUSPENSE_ID, SSR_DATA_ATTR, DEFAULT_MAX_SSR_BYTES;
|
|
1615
|
+
var SAFE_ATTR_NAME, VOID_ELEMENTS, nativeAccessorsByRealm, SAFE_ID, SAFE_SUSPENSE_ID, SSR_DATA_ATTR, DEFAULT_MAX_SSR_BYTES;
|
|
1316
1616
|
var init_ssr = __esm({
|
|
1317
1617
|
"src/platform/ssr.ts"() {
|
|
1318
1618
|
"use strict";
|
|
1319
1619
|
init_dev();
|
|
1320
1620
|
init_dispose();
|
|
1321
1621
|
init_ssr_context();
|
|
1622
|
+
init_elementPolicy();
|
|
1623
|
+
init_guards();
|
|
1322
1624
|
init_headEntry();
|
|
1323
1625
|
init_metaRefresh();
|
|
1324
1626
|
init_sanitize();
|
|
@@ -1339,6 +1641,7 @@ var init_ssr = __esm({
|
|
|
1339
1641
|
"track",
|
|
1340
1642
|
"wbr"
|
|
1341
1643
|
]);
|
|
1644
|
+
nativeAccessorsByRealm = /* @__PURE__ */ new WeakMap();
|
|
1342
1645
|
SAFE_ID = /^[A-Za-z0-9_-]+$/;
|
|
1343
1646
|
SAFE_SUSPENSE_ID = /^[A-Za-z0-9_-]+$/;
|
|
1344
1647
|
SSR_DATA_ATTR = "__SIBU_SSR_DATA__";
|
|
@@ -1425,6 +1728,7 @@ __export(plugins_exports, {
|
|
|
1425
1728
|
setRouteTransition: () => setRouteTransition,
|
|
1426
1729
|
setRoutes: () => setRoutes,
|
|
1427
1730
|
t: () => t,
|
|
1731
|
+
translated: () => translated,
|
|
1428
1732
|
triggerPluginError: () => triggerPluginError,
|
|
1429
1733
|
triggerPluginMount: () => triggerPluginMount,
|
|
1430
1734
|
triggerPluginUnmount: () => triggerPluginUnmount
|
|
@@ -1440,26 +1744,45 @@ init_sanitize();
|
|
|
1440
1744
|
|
|
1441
1745
|
// src/utils/setSafeAttribute.ts
|
|
1442
1746
|
init_dev();
|
|
1747
|
+
init_elementPolicy();
|
|
1443
1748
|
init_sanitize();
|
|
1444
|
-
var
|
|
1445
|
-
var
|
|
1749
|
+
var HTML_NS2 = "http://www.w3.org/1999/xhtml";
|
|
1750
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
1446
1751
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
1447
1752
|
var XML_NS = "http://www.w3.org/XML/1998/namespace";
|
|
1448
1753
|
var BOOLEAN_IDL_ATTRS = /* @__PURE__ */ new Set(["checked", "disabled", "selected"]);
|
|
1449
1754
|
function isHtmlElement(el) {
|
|
1450
|
-
return el.namespaceURI === null || el.namespaceURI ===
|
|
1755
|
+
return el.namespaceURI === null || el.namespaceURI === HTML_NS2;
|
|
1756
|
+
}
|
|
1757
|
+
function warnContextualRefusal(label2, name, refusal) {
|
|
1758
|
+
devWarnLazy(() => {
|
|
1759
|
+
const reasons = [
|
|
1760
|
+
"",
|
|
1761
|
+
'the element would become a <meta http-equiv="refresh"> directive the shared refresh policy forbids (a destination outside the URL allowlist, or a directive too malformed to read unambiguously)',
|
|
1762
|
+
"a <meta> whose http-equiv or content is reactive may never carry a refresh directive: a browser schedules the navigation as soon as the directive is valid, and nothing can withdraw it when the state changes back",
|
|
1763
|
+
"a runtime value may not choose the program a <script> runs; name the script in static template source, or load it through Head({ script }) as an explicit trust decision",
|
|
1764
|
+
"an SVG animation may not target a URL, event-handler or nested-document attribute; its to / values would be written into that attribute without passing the URL policy",
|
|
1765
|
+
'a runtime-chosen href may not become an applied <link rel="stylesheet">: a well-formed URL is not a trusted stylesheet. Name the stylesheet in static template source, or load a runtime-chosen one through Head({ link }) as an explicit trust decision'
|
|
1766
|
+
];
|
|
1767
|
+
return `${label2}: refusing "${name}" in this element's context \u2014 ${reasons[refusal]}. The write was not performed.`;
|
|
1768
|
+
});
|
|
1451
1769
|
}
|
|
1452
1770
|
function setProp(el, key, val) {
|
|
1453
1771
|
el[key] = val;
|
|
1454
1772
|
}
|
|
1455
1773
|
function namespaceFor(el, name) {
|
|
1456
|
-
if (el.namespaceURI !==
|
|
1774
|
+
if (el.namespaceURI !== SVG_NS2) return null;
|
|
1457
1775
|
const lower = name.toLowerCase();
|
|
1458
1776
|
if (lower.startsWith("xlink:")) return XLINK_NS;
|
|
1459
1777
|
if (lower.startsWith("xml:")) return XML_NS;
|
|
1460
1778
|
return null;
|
|
1461
1779
|
}
|
|
1462
1780
|
function setSafeAttribute(el, name, value, options = {}) {
|
|
1781
|
+
const written = commitSafeAttribute(el, name, value, options);
|
|
1782
|
+
if (el.localName === "link") settleAttributeProvenance(el, name, options.reactive ? "reactive" : "runtime");
|
|
1783
|
+
return written;
|
|
1784
|
+
}
|
|
1785
|
+
function commitSafeAttribute(el, name, value, options) {
|
|
1463
1786
|
const ns = namespaceFor(el, name);
|
|
1464
1787
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
1465
1788
|
if (isEventHandlerAttr(name)) {
|
|
@@ -1472,6 +1795,14 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1472
1795
|
else el.removeAttribute(name);
|
|
1473
1796
|
return false;
|
|
1474
1797
|
}
|
|
1798
|
+
const pending = value == null || value === false ? null : value === true ? "" : String(value);
|
|
1799
|
+
const refusal = contextualAttributeRefusal(el, name, pending, options.reactive ? "reactive" : "runtime");
|
|
1800
|
+
if (refusal !== ContextualRefusal.None) {
|
|
1801
|
+
warnContextualRefusal(options.label ?? "setSafeAttribute", name, refusal);
|
|
1802
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
1803
|
+
else el.removeAttribute(name);
|
|
1804
|
+
return false;
|
|
1805
|
+
}
|
|
1475
1806
|
if (value == null) {
|
|
1476
1807
|
if (ns) el.removeAttributeNS(ns, localName);
|
|
1477
1808
|
else el.removeAttribute(name);
|
|
@@ -1515,7 +1846,12 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1515
1846
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
1516
1847
|
return true;
|
|
1517
1848
|
}
|
|
1518
|
-
const safe =
|
|
1849
|
+
const safe = str === "" ? "" : resolveAttributeValue(name, str, { element: el });
|
|
1850
|
+
if (safe === null) {
|
|
1851
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
1852
|
+
else el.removeAttribute(name);
|
|
1853
|
+
return true;
|
|
1854
|
+
}
|
|
1519
1855
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
1520
1856
|
if (current === safe) return true;
|
|
1521
1857
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -2019,7 +2355,7 @@ function forEachSubscriber(signal2, visit) {
|
|
|
2019
2355
|
}
|
|
2020
2356
|
|
|
2021
2357
|
// src/reactivity/track.ts
|
|
2022
|
-
var _runtimeVersion = true ? "4.
|
|
2358
|
+
var _runtimeVersion = true ? "4.8.0" : "dev";
|
|
2023
2359
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
2024
2360
|
function resolveReactiveApi() {
|
|
2025
2361
|
const g2 = globalThis;
|
|
@@ -2090,7 +2426,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
2090
2426
|
reportError(err, { phase: "binding", name: `bindAttribute("${attr}")`, node: el });
|
|
2091
2427
|
return;
|
|
2092
2428
|
}
|
|
2093
|
-
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")
|
|
2429
|
+
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")`, reactive: true });
|
|
2094
2430
|
}
|
|
2095
2431
|
return reactiveBinding2(commit, el);
|
|
2096
2432
|
}
|
|
@@ -2270,13 +2606,10 @@ function bindChildNode(placeholder, getter) {
|
|
|
2270
2606
|
}
|
|
2271
2607
|
|
|
2272
2608
|
// src/core/rendering/tagFactory.ts
|
|
2609
|
+
init_elementPolicy();
|
|
2273
2610
|
init_sanitize();
|
|
2274
2611
|
init_dispose();
|
|
2275
|
-
var
|
|
2276
|
-
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
2277
|
-
function isBlockedTag(tag) {
|
|
2278
|
-
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
2279
|
-
}
|
|
2612
|
+
var SVG_NS3 = "http://www.w3.org/2000/svg";
|
|
2280
2613
|
var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
2281
2614
|
"config",
|
|
2282
2615
|
"location",
|
|
@@ -2303,8 +2636,35 @@ function toKebab(prop) {
|
|
|
2303
2636
|
}
|
|
2304
2637
|
function applyStyle(el, style2) {
|
|
2305
2638
|
if (typeof style2 === "function") {
|
|
2639
|
+
const getter = style2;
|
|
2640
|
+
let written = [];
|
|
2641
|
+
let wroteString = false;
|
|
2306
2642
|
const teardown = reactiveBinding2(() => {
|
|
2307
|
-
|
|
2643
|
+
const value = getter();
|
|
2644
|
+
if (value === null || typeof value !== "object") {
|
|
2645
|
+
written = [];
|
|
2646
|
+
wroteString = true;
|
|
2647
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(value), { element: el }));
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2650
|
+
const decl = el.style;
|
|
2651
|
+
if (wroteString) {
|
|
2652
|
+
el.removeAttribute("style");
|
|
2653
|
+
wroteString = false;
|
|
2654
|
+
}
|
|
2655
|
+
const next = [];
|
|
2656
|
+
for (const prop in value) {
|
|
2657
|
+
if (!Object.hasOwn(value, prop)) continue;
|
|
2658
|
+
const val = value[prop];
|
|
2659
|
+
if (val == null) continue;
|
|
2660
|
+
const name = toKebab(prop);
|
|
2661
|
+
next.push(name);
|
|
2662
|
+
decl.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
2663
|
+
}
|
|
2664
|
+
for (let i2 = 0; i2 < written.length; i2++) {
|
|
2665
|
+
if (next.indexOf(written[i2]) === -1) decl.removeProperty(written[i2]);
|
|
2666
|
+
}
|
|
2667
|
+
written = next;
|
|
2308
2668
|
}, el);
|
|
2309
2669
|
registerDisposer(el, teardown);
|
|
2310
2670
|
return;
|
|
@@ -2315,25 +2675,27 @@ function applyStyle(el, style2) {
|
|
|
2315
2675
|
}
|
|
2316
2676
|
const htmlEl = el;
|
|
2317
2677
|
for (const prop in style2) {
|
|
2678
|
+
if (!Object.hasOwn(style2, prop)) continue;
|
|
2318
2679
|
const val = style2[prop];
|
|
2319
2680
|
const name = toKebab(prop);
|
|
2320
2681
|
if (typeof val === "function") {
|
|
2321
2682
|
const getter = val;
|
|
2322
2683
|
const teardown = reactiveBinding2(() => {
|
|
2323
|
-
htmlEl.style.setProperty(name,
|
|
2684
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(getter()), { element: el }));
|
|
2324
2685
|
}, el);
|
|
2325
2686
|
registerDisposer(el, teardown);
|
|
2326
2687
|
} else {
|
|
2327
|
-
htmlEl.style.setProperty(name,
|
|
2688
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
2328
2689
|
}
|
|
2329
2690
|
}
|
|
2330
2691
|
}
|
|
2331
2692
|
function resolveClassValue(cls) {
|
|
2332
2693
|
if (typeof cls === "string") return cls;
|
|
2333
|
-
if (typeof cls === "function") return cls();
|
|
2694
|
+
if (typeof cls === "function") return cls() || "";
|
|
2334
2695
|
if (!cls) return "";
|
|
2335
2696
|
let out = "";
|
|
2336
2697
|
for (const name in cls) {
|
|
2698
|
+
if (!Object.hasOwn(cls, name)) continue;
|
|
2337
2699
|
const val = cls[name];
|
|
2338
2700
|
const active = typeof val === "function" ? val() : val;
|
|
2339
2701
|
if (active) out = out ? `${out} ${name}` : name;
|
|
@@ -2347,7 +2709,9 @@ function applyClass(el, cls) {
|
|
|
2347
2709
|
}
|
|
2348
2710
|
if (typeof cls === "function") {
|
|
2349
2711
|
const teardown = reactiveBinding2(() => {
|
|
2350
|
-
|
|
2712
|
+
const value = cls();
|
|
2713
|
+
if (value == null || value === false) el.removeAttribute("class");
|
|
2714
|
+
else el.setAttribute("class", value);
|
|
2351
2715
|
}, el);
|
|
2352
2716
|
registerDisposer(el, teardown);
|
|
2353
2717
|
return;
|
|
@@ -2356,6 +2720,7 @@ function applyClass(el, cls) {
|
|
|
2356
2720
|
let hasReactive = false;
|
|
2357
2721
|
let result = "";
|
|
2358
2722
|
for (const name in obj) {
|
|
2723
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
2359
2724
|
const val = obj[name];
|
|
2360
2725
|
if (typeof val === "function") {
|
|
2361
2726
|
hasReactive = true;
|
|
@@ -2367,6 +2732,7 @@ function applyClass(el, cls) {
|
|
|
2367
2732
|
const update = () => {
|
|
2368
2733
|
let r = "";
|
|
2369
2734
|
for (const name in obj) {
|
|
2735
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
2370
2736
|
const val = obj[name];
|
|
2371
2737
|
const active = typeof val === "function" ? val() : val;
|
|
2372
2738
|
if (active) r = r ? `${r} ${name}` : name;
|
|
@@ -2429,8 +2795,8 @@ function appendChildren(el, nodes) {
|
|
|
2429
2795
|
}
|
|
2430
2796
|
}
|
|
2431
2797
|
}
|
|
2432
|
-
|
|
2433
|
-
const blocked =
|
|
2798
|
+
function tagFactory(tag, ns) {
|
|
2799
|
+
const blocked = isBlockedElement(tag);
|
|
2434
2800
|
return (first, second) => {
|
|
2435
2801
|
if (blocked) {
|
|
2436
2802
|
throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
@@ -2478,7 +2844,9 @@ var tagFactory = (tag, ns) => {
|
|
|
2478
2844
|
const pClass = props.class;
|
|
2479
2845
|
if (pClass != null) applyClass(el, pClass);
|
|
2480
2846
|
const pId = props.id;
|
|
2481
|
-
if (pId
|
|
2847
|
+
if (typeof pId === "function") {
|
|
2848
|
+
registerDisposer(el, bindAttribute(el, "id", pId));
|
|
2849
|
+
} else if (pId != null) {
|
|
2482
2850
|
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
2483
2851
|
devWarn(
|
|
2484
2852
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
@@ -2491,6 +2859,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2491
2859
|
const pOn = props.on;
|
|
2492
2860
|
if (pOn) {
|
|
2493
2861
|
for (const ev in pOn) {
|
|
2862
|
+
if (!Object.hasOwn(pOn, ev)) continue;
|
|
2494
2863
|
const handler = pOn[ev];
|
|
2495
2864
|
if (typeof handler === "function") {
|
|
2496
2865
|
el.addEventListener(ev, handler);
|
|
@@ -2517,6 +2886,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2517
2886
|
continue;
|
|
2518
2887
|
// already handled above / below
|
|
2519
2888
|
default: {
|
|
2889
|
+
if (!Object.hasOwn(props, key)) continue;
|
|
2520
2890
|
const value = props[key];
|
|
2521
2891
|
if (value == null) continue;
|
|
2522
2892
|
if (isEventHandlerAttr(key)) continue;
|
|
@@ -2528,12 +2898,10 @@ var tagFactory = (tag, ns) => {
|
|
|
2528
2898
|
}
|
|
2529
2899
|
}
|
|
2530
2900
|
}
|
|
2531
|
-
if (
|
|
2532
|
-
props.onElement(el);
|
|
2533
|
-
}
|
|
2901
|
+
if (typeof props.onElement === "function") props.onElement(el);
|
|
2534
2902
|
return el;
|
|
2535
2903
|
};
|
|
2536
|
-
}
|
|
2904
|
+
}
|
|
2537
2905
|
|
|
2538
2906
|
// src/core/rendering/html.ts
|
|
2539
2907
|
var html = tagFactory("html");
|
|
@@ -2608,7 +2976,7 @@ var param = tagFactory("param");
|
|
|
2608
2976
|
var picture = tagFactory("picture");
|
|
2609
2977
|
var portal = tagFactory("portal");
|
|
2610
2978
|
var source = tagFactory("source");
|
|
2611
|
-
var svg = tagFactory("svg",
|
|
2979
|
+
var svg = tagFactory("svg", SVG_NS3);
|
|
2612
2980
|
var math = tagFactory("math");
|
|
2613
2981
|
var canvas = tagFactory("canvas");
|
|
2614
2982
|
var noscript = tagFactory("noscript");
|
|
@@ -2649,26 +3017,26 @@ var base = tagFactory("base");
|
|
|
2649
3017
|
var link = tagFactory("link");
|
|
2650
3018
|
var meta = tagFactory("meta");
|
|
2651
3019
|
var style = tagFactory("style");
|
|
2652
|
-
var circle = tagFactory("circle",
|
|
2653
|
-
var ellipse = tagFactory("ellipse",
|
|
2654
|
-
var g = tagFactory("g",
|
|
2655
|
-
var line = tagFactory("line",
|
|
2656
|
-
var path = tagFactory("path",
|
|
2657
|
-
var polygon = tagFactory("polygon",
|
|
2658
|
-
var polyline = tagFactory("polyline",
|
|
2659
|
-
var rect = tagFactory("rect",
|
|
2660
|
-
var text = tagFactory("text",
|
|
2661
|
-
var tspan = tagFactory("tspan",
|
|
2662
|
-
var defs = tagFactory("defs",
|
|
2663
|
-
var clipPath = tagFactory("clipPath",
|
|
2664
|
-
var mask = tagFactory("mask",
|
|
2665
|
-
var pattern = tagFactory("pattern",
|
|
2666
|
-
var linearGradient = tagFactory("linearGradient",
|
|
2667
|
-
var radialGradient = tagFactory("radialGradient",
|
|
2668
|
-
var stop = tagFactory("stop",
|
|
2669
|
-
var use = tagFactory("use",
|
|
2670
|
-
var symbol = tagFactory("symbol",
|
|
2671
|
-
var marker = tagFactory("marker",
|
|
3020
|
+
var circle = tagFactory("circle", SVG_NS3);
|
|
3021
|
+
var ellipse = tagFactory("ellipse", SVG_NS3);
|
|
3022
|
+
var g = tagFactory("g", SVG_NS3);
|
|
3023
|
+
var line = tagFactory("line", SVG_NS3);
|
|
3024
|
+
var path = tagFactory("path", SVG_NS3);
|
|
3025
|
+
var polygon = tagFactory("polygon", SVG_NS3);
|
|
3026
|
+
var polyline = tagFactory("polyline", SVG_NS3);
|
|
3027
|
+
var rect = tagFactory("rect", SVG_NS3);
|
|
3028
|
+
var text = tagFactory("text", SVG_NS3);
|
|
3029
|
+
var tspan = tagFactory("tspan", SVG_NS3);
|
|
3030
|
+
var defs = tagFactory("defs", SVG_NS3);
|
|
3031
|
+
var clipPath = tagFactory("clipPath", SVG_NS3);
|
|
3032
|
+
var mask = tagFactory("mask", SVG_NS3);
|
|
3033
|
+
var pattern = tagFactory("pattern", SVG_NS3);
|
|
3034
|
+
var linearGradient = tagFactory("linearGradient", SVG_NS3);
|
|
3035
|
+
var radialGradient = tagFactory("radialGradient", SVG_NS3);
|
|
3036
|
+
var stop = tagFactory("stop", SVG_NS3);
|
|
3037
|
+
var use = tagFactory("use", SVG_NS3);
|
|
3038
|
+
var symbol = tagFactory("symbol", SVG_NS3);
|
|
3039
|
+
var marker = tagFactory("marker", SVG_NS3);
|
|
2672
3040
|
var center = tagFactory("center");
|
|
2673
3041
|
var font = tagFactory("font");
|
|
2674
3042
|
var marquee = tagFactory("marquee");
|
|
@@ -2725,6 +3093,16 @@ var isBatching = API2.isBatching;
|
|
|
2725
3093
|
|
|
2726
3094
|
// src/core/signals/signal.ts
|
|
2727
3095
|
init_dev();
|
|
3096
|
+
|
|
3097
|
+
// src/core/devtoolsHook.ts
|
|
3098
|
+
function emitDevtools(hook, event, payload) {
|
|
3099
|
+
try {
|
|
3100
|
+
hook.emit(event, payload);
|
|
3101
|
+
} catch {
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3105
|
+
// src/core/signals/signal.ts
|
|
2728
3106
|
var _g = globalThis;
|
|
2729
3107
|
function signal(initial, options) {
|
|
2730
3108
|
const state2 = {
|
|
@@ -2757,7 +3135,7 @@ function signal(initial, options) {
|
|
|
2757
3135
|
state2.__v++;
|
|
2758
3136
|
if (DEV) {
|
|
2759
3137
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2760
|
-
if (hook) hook
|
|
3138
|
+
if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
2761
3139
|
}
|
|
2762
3140
|
if (!enqueueBatchedSignal(state2)) {
|
|
2763
3141
|
notifySubscribers2(state2);
|
|
@@ -2771,7 +3149,7 @@ function signal(initial, options) {
|
|
|
2771
3149
|
state2.value = newValue;
|
|
2772
3150
|
state2.__v++;
|
|
2773
3151
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2774
|
-
if (hook) hook
|
|
3152
|
+
if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
2775
3153
|
if (!enqueueBatchedSignal(state2)) {
|
|
2776
3154
|
notifySubscribers2(state2);
|
|
2777
3155
|
}
|
|
@@ -2790,7 +3168,7 @@ function signal(initial, options) {
|
|
|
2790
3168
|
}
|
|
2791
3169
|
if (DEV) {
|
|
2792
3170
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2793
|
-
if (hook) hook
|
|
3171
|
+
if (hook) emitDevtools(hook, "signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
2794
3172
|
}
|
|
2795
3173
|
return [get, set];
|
|
2796
3174
|
}
|
|
@@ -2807,14 +3185,20 @@ function globalSingleton(key, create) {
|
|
|
2807
3185
|
// src/plugins/i18n.ts
|
|
2808
3186
|
var _i18n = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.i18n.v1"), () => ({
|
|
2809
3187
|
locale: signal("en"),
|
|
2810
|
-
locales: /* @__PURE__ */ Object.create(null)
|
|
3188
|
+
locales: /* @__PURE__ */ Object.create(null),
|
|
3189
|
+
revision: signal(0)
|
|
2811
3190
|
}));
|
|
2812
3191
|
var [clientLocale, setClientLocale] = _i18n.locale;
|
|
2813
3192
|
var locales = _i18n.locales;
|
|
3193
|
+
var [revision, setRevision] = _i18n.revision ?? (_i18n.revision = signal(0));
|
|
2814
3194
|
function dictionaryFor(locale) {
|
|
2815
3195
|
return Object.hasOwn(locales, locale) ? locales[locale] : void 0;
|
|
2816
3196
|
}
|
|
3197
|
+
function trackDictionaries() {
|
|
3198
|
+
if (!getRequestStore()) revision();
|
|
3199
|
+
}
|
|
2817
3200
|
function lookup(key) {
|
|
3201
|
+
trackDictionaries();
|
|
2818
3202
|
const dictionary = dictionaryFor(getLocale());
|
|
2819
3203
|
if (dictionary === void 0 || !Object.hasOwn(dictionary, key)) return void 0;
|
|
2820
3204
|
const message = dictionary[key];
|
|
@@ -2835,6 +3219,7 @@ function getLocale() {
|
|
|
2835
3219
|
}
|
|
2836
3220
|
return clientLocale();
|
|
2837
3221
|
}
|
|
3222
|
+
_i18n.getLocale ?? (_i18n.getLocale = getLocale);
|
|
2838
3223
|
function registerTranslations(locale, messages) {
|
|
2839
3224
|
const prepared = { ...messages };
|
|
2840
3225
|
const merged = Object.assign(/* @__PURE__ */ Object.create(null), dictionaryFor(locale), prepared);
|
|
@@ -2844,18 +3229,29 @@ function registerTranslations(locale, messages) {
|
|
|
2844
3229
|
enumerable: true,
|
|
2845
3230
|
configurable: true
|
|
2846
3231
|
});
|
|
3232
|
+
setRevision((n) => n + 1);
|
|
3233
|
+
}
|
|
3234
|
+
function resolveParam(params, name) {
|
|
3235
|
+
if (!Object.hasOwn(params, name)) return "";
|
|
3236
|
+
const raw = params[name];
|
|
3237
|
+
const value = typeof raw === "function" ? raw() : raw;
|
|
3238
|
+
return value == null ? "" : String(value);
|
|
2847
3239
|
}
|
|
2848
3240
|
function t(key, params) {
|
|
2849
3241
|
const message = lookup(key) ?? key;
|
|
2850
|
-
return params ? message.replace(/\{(\w+)\}/g, (_, p2) =>
|
|
3242
|
+
return params ? message.replace(/\{(\w+)\}/g, (_, p2) => resolveParam(params, p2)) : message;
|
|
3243
|
+
}
|
|
3244
|
+
function translated(key, params) {
|
|
3245
|
+
return () => t(key, params);
|
|
2851
3246
|
}
|
|
2852
3247
|
function Trans(key, params) {
|
|
2853
|
-
return span((
|
|
3248
|
+
return span(translated(key, params));
|
|
2854
3249
|
}
|
|
2855
3250
|
function hasTranslation(key) {
|
|
2856
3251
|
return lookup(key) !== void 0;
|
|
2857
3252
|
}
|
|
2858
3253
|
function getAvailableLocales() {
|
|
3254
|
+
trackDictionaries();
|
|
2859
3255
|
return Object.keys(locales);
|
|
2860
3256
|
}
|
|
2861
3257
|
|
|
@@ -2981,12 +3377,17 @@ function effect(effectFn, options) {
|
|
|
2981
3377
|
try {
|
|
2982
3378
|
retrack2(ctx.bodyFn, ctx.subscriber);
|
|
2983
3379
|
if (ctx.rerunPending) drainReruns(ctx);
|
|
3380
|
+
} catch (err) {
|
|
3381
|
+
ctx.disposed = true;
|
|
3382
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
3383
|
+
cleanup2(ctx.subscriber);
|
|
3384
|
+
throw err;
|
|
2984
3385
|
} finally {
|
|
2985
3386
|
ctx.running = false;
|
|
2986
3387
|
ctx.rerunPending = false;
|
|
2987
3388
|
}
|
|
2988
3389
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2989
|
-
if (hook) hook
|
|
3390
|
+
if (hook) emitDevtools(hook, "effect:create", { effectFn });
|
|
2990
3391
|
return () => disposeEffect(ctx);
|
|
2991
3392
|
}
|
|
2992
3393
|
|
|
@@ -4161,6 +4562,30 @@ function afterEach(hook) {
|
|
|
4161
4562
|
return _routerRef.current.afterEach(hook);
|
|
4162
4563
|
}
|
|
4163
4564
|
var routeCleanups = [];
|
|
4565
|
+
var ownParamNamesCache = /* @__PURE__ */ new WeakMap();
|
|
4566
|
+
function ownParamNames(record) {
|
|
4567
|
+
const cached = ownParamNamesCache.get(record);
|
|
4568
|
+
if (cached) return cached;
|
|
4569
|
+
const aliases = record.alias == null ? [] : Array.isArray(record.alias) ? record.alias : [record.alias];
|
|
4570
|
+
const names = /* @__PURE__ */ new Set();
|
|
4571
|
+
for (const pattern2 of [record.path, ...aliases]) {
|
|
4572
|
+
for (const m of pattern2.matchAll(/\/:([^/]+)/g)) {
|
|
4573
|
+
names.add(m[1].endsWith("?") ? m[1].slice(0, -1) : m[1]);
|
|
4574
|
+
}
|
|
4575
|
+
}
|
|
4576
|
+
const result = [...names];
|
|
4577
|
+
ownParamNamesCache.set(record, result);
|
|
4578
|
+
return result;
|
|
4579
|
+
}
|
|
4580
|
+
function instanceKey(owner, records, route2) {
|
|
4581
|
+
const custom = owner.key;
|
|
4582
|
+
if (custom) return untracked2(() => String(custom(route2)));
|
|
4583
|
+
const parts = [];
|
|
4584
|
+
for (const record of records) {
|
|
4585
|
+
for (const name of ownParamNames(record)) parts.push(name, route2.params[name] ?? null);
|
|
4586
|
+
}
|
|
4587
|
+
return JSON.stringify(parts);
|
|
4588
|
+
}
|
|
4164
4589
|
function Route() {
|
|
4165
4590
|
const anchor = document.createComment("route-outlet");
|
|
4166
4591
|
let currentNode = null;
|
|
@@ -4168,6 +4593,7 @@ function Route() {
|
|
|
4168
4593
|
let errorNode = null;
|
|
4169
4594
|
let navSeq = 0;
|
|
4170
4595
|
let currentTopRoute = null;
|
|
4596
|
+
let currentKey = null;
|
|
4171
4597
|
let routeTorn = false;
|
|
4172
4598
|
const commitTarget = (seq) => routeTorn || seq !== navSeq ? null : anchor.parentNode;
|
|
4173
4599
|
const release = (node) => {
|
|
@@ -4259,11 +4685,13 @@ function Route() {
|
|
|
4259
4685
|
const match = _routerRef.current["matcher"].match(route2.path);
|
|
4260
4686
|
if (!match) {
|
|
4261
4687
|
currentTopRoute = null;
|
|
4688
|
+
currentKey = null;
|
|
4262
4689
|
cleanupNodes();
|
|
4263
4690
|
return;
|
|
4264
4691
|
}
|
|
4265
4692
|
const routeDef = match.matched[0] || match.route;
|
|
4266
|
-
|
|
4693
|
+
const key = instanceKey(routeDef, [routeDef], route2);
|
|
4694
|
+
if (routeDef === currentTopRoute && key === currentKey && currentNode) {
|
|
4267
4695
|
return;
|
|
4268
4696
|
}
|
|
4269
4697
|
if ("redirect" in routeDef) {
|
|
@@ -4291,6 +4719,7 @@ function Route() {
|
|
|
4291
4719
|
}
|
|
4292
4720
|
if (node) {
|
|
4293
4721
|
currentTopRoute = routeDef;
|
|
4722
|
+
currentKey = key;
|
|
4294
4723
|
cleanupNodes();
|
|
4295
4724
|
parent.insertBefore(node, anchor.nextSibling);
|
|
4296
4725
|
currentNode = node;
|
|
@@ -4328,6 +4757,7 @@ function Route() {
|
|
|
4328
4757
|
routeTeardown();
|
|
4329
4758
|
cleanupNodes();
|
|
4330
4759
|
currentTopRoute = null;
|
|
4760
|
+
currentKey = null;
|
|
4331
4761
|
};
|
|
4332
4762
|
registerDisposer(anchor, routeCleanup);
|
|
4333
4763
|
routeCleanups.push(routeCleanup);
|
|
@@ -4503,30 +4933,10 @@ function RouterLink(props, children) {
|
|
|
4503
4933
|
const lkey = key.toLowerCase();
|
|
4504
4934
|
if (lkey === "href" || lkey[0] === "o" && lkey[1] === "n") return;
|
|
4505
4935
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4506
|
-
|
|
4507
|
-
if (isUrlAttribute(lkey)) {
|
|
4508
|
-
const safe = sanitizeUrl(str);
|
|
4509
|
-
if (safe) link2.setAttribute(key, safe);
|
|
4510
|
-
} else if (lkey === "style") {
|
|
4511
|
-
link2.setAttribute(key, sanitizeStyleAttribute(str, { element: link2 }));
|
|
4512
|
-
} else {
|
|
4513
|
-
link2.setAttribute(key, str);
|
|
4514
|
-
}
|
|
4936
|
+
setSafeAttribute(link2, key, String(value), { syncValueProperty: false, label: "RouterLink" });
|
|
4515
4937
|
}
|
|
4516
4938
|
});
|
|
4517
|
-
if (
|
|
4518
|
-
link2.textContent = content;
|
|
4519
|
-
} else if (content instanceof Node) {
|
|
4520
|
-
link2.appendChild(content);
|
|
4521
|
-
} else if (Array.isArray(content)) {
|
|
4522
|
-
content.forEach((child) => {
|
|
4523
|
-
if (typeof child === "string") {
|
|
4524
|
-
link2.appendChild(document.createTextNode(child));
|
|
4525
|
-
} else if (child instanceof Node) {
|
|
4526
|
-
link2.appendChild(child);
|
|
4527
|
-
}
|
|
4528
|
-
});
|
|
4529
|
-
}
|
|
4939
|
+
if (content !== void 0) appendChildren(link2, content);
|
|
4530
4940
|
const onLinkClick = (e) => {
|
|
4531
4941
|
if (e.defaultPrevented || target || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) {
|
|
4532
4942
|
return;
|
|
@@ -4688,6 +5098,7 @@ function Outlet() {
|
|
|
4688
5098
|
const anchor = document.createComment("route-outlet-nested");
|
|
4689
5099
|
let currentNode = null;
|
|
4690
5100
|
let currentChild = null;
|
|
5101
|
+
let currentKey = null;
|
|
4691
5102
|
let navSeq = 0;
|
|
4692
5103
|
let outletTorn = false;
|
|
4693
5104
|
const clearCurrent = () => {
|
|
@@ -4697,6 +5108,7 @@ function Outlet() {
|
|
|
4697
5108
|
currentNode = null;
|
|
4698
5109
|
}
|
|
4699
5110
|
currentChild = null;
|
|
5111
|
+
currentKey = null;
|
|
4700
5112
|
};
|
|
4701
5113
|
const commitTarget = (seq) => outletTorn || seq !== navSeq ? null : anchor.parentNode;
|
|
4702
5114
|
const release = (node) => {
|
|
@@ -4717,7 +5129,8 @@ function Outlet() {
|
|
|
4717
5129
|
clearCurrent();
|
|
4718
5130
|
return;
|
|
4719
5131
|
}
|
|
4720
|
-
|
|
5132
|
+
const key = instanceKey(childRoute, route2.matched.slice(1), route2);
|
|
5133
|
+
if (childRoute === currentChild && key === currentKey && currentNode) return;
|
|
4721
5134
|
try {
|
|
4722
5135
|
const cacheKey = `${route2.path}\0${childRoute.path}`;
|
|
4723
5136
|
const plan = await _routerRef.current.loadPlan(childRoute, cacheKey);
|
|
@@ -4733,6 +5146,7 @@ function Outlet() {
|
|
|
4733
5146
|
parent.insertBefore(node, anchor.nextSibling);
|
|
4734
5147
|
currentNode = node;
|
|
4735
5148
|
currentChild = childRoute;
|
|
5149
|
+
currentKey = key;
|
|
4736
5150
|
} catch (error) {
|
|
4737
5151
|
if (outletTorn || seq !== navSeq) return;
|
|
4738
5152
|
console.error("[Outlet] Failed to render child route:", error);
|
|
@@ -4755,6 +5169,7 @@ function Outlet() {
|
|
|
4755
5169
|
currentNode = null;
|
|
4756
5170
|
}
|
|
4757
5171
|
currentChild = null;
|
|
5172
|
+
currentKey = null;
|
|
4758
5173
|
};
|
|
4759
5174
|
registerDisposer(anchor, outletCleanup);
|
|
4760
5175
|
routeCleanups.push(outletCleanup);
|
|
@@ -4817,14 +5232,7 @@ function createMemoryRouter(routes, _initialPath = "/") {
|
|
|
4817
5232
|
|
|
4818
5233
|
// src/plugins/routerSSR.ts
|
|
4819
5234
|
init_ssr();
|
|
4820
|
-
|
|
4821
|
-
// src/utils/guards.ts
|
|
4822
|
-
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
4823
|
-
function isUnsafeKey(key) {
|
|
4824
|
-
return UNSAFE_KEYS.has(key);
|
|
4825
|
-
}
|
|
4826
|
-
|
|
4827
|
-
// src/plugins/routerSSR.ts
|
|
5235
|
+
init_guards();
|
|
4828
5236
|
init_headEntry();
|
|
4829
5237
|
init_sanitize();
|
|
4830
5238
|
function safeDecode(raw) {
|
|
@@ -5057,8 +5465,7 @@ function serializeRouteState(state2, nonce) {
|
|
|
5057
5465
|
return `<script${nonceAttr}>window.${SSR_ROUTE_STATE_KEY}=${json}</script>`;
|
|
5058
5466
|
}
|
|
5059
5467
|
function deserializeRouteState() {
|
|
5060
|
-
|
|
5061
|
-
return window[SSR_ROUTE_STATE_KEY];
|
|
5468
|
+
return readOwnGlobal(SSR_ROUTE_STATE_KEY);
|
|
5062
5469
|
}
|
|
5063
5470
|
function hydrateRouter(routes, options) {
|
|
5064
5471
|
const serverState = deserializeRouteState();
|
|
@@ -5498,7 +5905,7 @@ var CDN_ENTRY_POINTS = {
|
|
|
5498
5905
|
};
|
|
5499
5906
|
var packageInfo = {
|
|
5500
5907
|
name: "sibujs",
|
|
5501
|
-
version: true ? "4.
|
|
5908
|
+
version: true ? "4.8.0" : "dev",
|
|
5502
5909
|
entryPoints: MODULE_ENTRY_POINTS,
|
|
5503
5910
|
/**
|
|
5504
5911
|
* Generate the package.json `exports` map. Module entries resolve to the
|
|
@@ -5643,7 +6050,7 @@ var env = {
|
|
|
5643
6050
|
};
|
|
5644
6051
|
|
|
5645
6052
|
// src/plugins/versioning.ts
|
|
5646
|
-
var VERSION = true ? "4.
|
|
6053
|
+
var VERSION = true ? "4.8.0" : "dev";
|
|
5647
6054
|
var NUM = "(?:0|[1-9]\\d*)";
|
|
5648
6055
|
var PRE_ID = `(?:${NUM}|\\d*[a-zA-Z-][0-9a-zA-Z-]*)`;
|
|
5649
6056
|
var BUILD_ID = "[0-9a-zA-Z-]+";
|
|
@@ -5925,15 +6332,18 @@ function extractRangeTarget(range) {
|
|
|
5925
6332
|
// src/plugins/startup.ts
|
|
5926
6333
|
init_errors();
|
|
5927
6334
|
init_ssr();
|
|
6335
|
+
init_sanitize();
|
|
5928
6336
|
function preloadCritical(resources) {
|
|
5929
6337
|
if (typeof document === "undefined") return;
|
|
5930
6338
|
for (const resource of resources) {
|
|
5931
|
-
const
|
|
6339
|
+
const href = sanitizeUrl(resource.href);
|
|
6340
|
+
if (!href) continue;
|
|
6341
|
+
const safeHref = typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(href) : href.replace(/["\\]/g, "\\$&");
|
|
5932
6342
|
const existing = document.querySelector(`link[rel="preload"][href="${safeHref}"]`);
|
|
5933
6343
|
if (existing) continue;
|
|
5934
6344
|
const link2 = document.createElement("link");
|
|
5935
6345
|
link2.rel = "preload";
|
|
5936
|
-
link2.href =
|
|
6346
|
+
link2.href = href;
|
|
5937
6347
|
link2.setAttribute("as", resource.as);
|
|
5938
6348
|
if (resource.type) {
|
|
5939
6349
|
link2.type = resource.type;
|
|
@@ -6241,6 +6651,7 @@ function createBootSequence() {
|
|
|
6241
6651
|
setRouteTransition,
|
|
6242
6652
|
setRoutes,
|
|
6243
6653
|
t,
|
|
6654
|
+
translated,
|
|
6244
6655
|
triggerPluginError,
|
|
6245
6656
|
triggerPluginMount,
|
|
6246
6657
|
triggerPluginUnmount
|