sibujs 4.7.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/dist/browser.cjs +45 -4
- package/dist/browser.d.cts +23 -0
- package/dist/browser.d.ts +23 -0
- package/dist/browser.js +6 -5
- package/dist/build.cjs +513 -78
- package/dist/build.d.cts +22 -8
- package/dist/build.d.ts +22 -8
- package/dist/build.js +68 -21
- package/dist/cdn.dev.global.js +15 -13
- package/dist/cdn.full.dev.global.js +15 -13
- package/dist/cdn.full.global.js +14 -12
- package/dist/cdn.global.js +14 -12
- package/dist/chunk-3ACAAQIN.js +224 -0
- package/dist/{chunk-DKXRACVN.js → chunk-44MTL7ED.js} +6 -6
- package/dist/{chunk-3QWBSL5R.js → chunk-4WMSTZ7J.js} +8 -5
- package/dist/{chunk-H3SRKIYX.js → chunk-62BDYGAG.js} +8 -0
- package/dist/{chunk-BSY63EM6.js → chunk-C5PEWEGH.js} +20 -5
- package/dist/{chunk-BC2SECJD.js → chunk-C7AA2CZX.js} +1 -1
- package/dist/{chunk-SLM3IA34.js → chunk-CZPRSWSS.js} +1 -1
- package/dist/{chunk-FQRUXCEE.js → chunk-DSID757X.js} +1 -1
- package/dist/{chunk-ZVL7TY4K.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-Z3OHK6QT.js → chunk-GSGNX35Q.js} +5 -5
- package/dist/{chunk-XYV3EDB7.js → chunk-J3YQ457H.js} +37 -20
- package/dist/{chunk-VZSG24LS.js → chunk-JUTFX2RM.js} +18 -10
- package/dist/{chunk-RUSSKG6G.js → chunk-KJ3UKABJ.js} +1 -1
- package/dist/{chunk-UNWRJRKC.js → chunk-LI4W3U6C.js} +1 -1
- package/dist/{chunk-FNJXNGYZ.js → chunk-O6TRVMJI.js} +58 -6
- package/dist/{chunk-7LUJQAOJ.js → chunk-Q5J2LVKH.js} +1 -1
- package/dist/{chunk-4AWA2PVD.js → chunk-QGMSESDD.js} +10 -5
- package/dist/{chunk-XZR4PXRE.js → chunk-RGLPEBDE.js} +13 -10
- package/dist/{chunk-JWKYU5GV.js → chunk-TQQUN4WR.js} +1 -1
- package/dist/{chunk-WOLJZUFQ.js → chunk-UCNP3HVM.js} +12 -8
- package/dist/{chunk-WEQ3DMVL.js → chunk-V3LHZSU5.js} +1 -1
- package/dist/{chunk-UOL2ECCS.js → chunk-VWT3VXPL.js} +18 -12
- package/dist/{chunk-2BPG2XDA.js → chunk-ZVLHNEEL.js} +17 -35
- 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 +9 -2
- package/dist/data.js +6 -6
- package/dist/devtools.cjs +1 -1
- package/dist/devtools.js +5 -5
- package/dist/ecosystem.cjs +400 -37
- package/dist/ecosystem.js +9 -8
- package/dist/extras.cjs +621 -252
- package/dist/extras.d.cts +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/extras.js +24 -23
- package/dist/index.cjs +464 -70
- package/dist/index.d.cts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +16 -12
- package/dist/motion.cjs +1 -1
- package/dist/motion.js +3 -3
- package/dist/patterns.cjs +10 -7
- package/dist/patterns.js +6 -6
- package/dist/performance.cjs +31 -2
- package/dist/performance.d.cts +12 -2
- package/dist/performance.d.ts +12 -2
- package/dist/performance.js +8 -6
- package/dist/plugins.cjs +558 -231
- package/dist/plugins.d.cts +8 -3
- package/dist/plugins.d.ts +8 -3
- package/dist/plugins.js +22 -28
- package/dist/{ssr-XOTUASDO.js → ssr-5OWAH3U2.js} +4 -2
- package/dist/{ssr-Bli9XRW5.d.ts → ssr-C8hgIAw7.d.cts} +6 -0
- package/dist/{ssr-Bli9XRW5.d.cts → ssr-C8hgIAw7.d.ts} +6 -0
- package/dist/ssr.cjs +457 -131
- package/dist/ssr.d.cts +55 -5
- package/dist/ssr.d.ts +55 -5
- package/dist/ssr.js +11 -9
- package/dist/testing.cjs +3 -3
- package/dist/testing.js +4 -4
- package/dist/ui.cjs +608 -240
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +9 -8
- package/dist/widgets.cjs +1 -1
- package/dist/widgets.js +7 -7
- package/package.json +5 -4
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__";
|
|
@@ -1441,26 +1744,45 @@ init_sanitize();
|
|
|
1441
1744
|
|
|
1442
1745
|
// src/utils/setSafeAttribute.ts
|
|
1443
1746
|
init_dev();
|
|
1747
|
+
init_elementPolicy();
|
|
1444
1748
|
init_sanitize();
|
|
1445
|
-
var
|
|
1446
|
-
var
|
|
1749
|
+
var HTML_NS2 = "http://www.w3.org/1999/xhtml";
|
|
1750
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
1447
1751
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
1448
1752
|
var XML_NS = "http://www.w3.org/XML/1998/namespace";
|
|
1449
1753
|
var BOOLEAN_IDL_ATTRS = /* @__PURE__ */ new Set(["checked", "disabled", "selected"]);
|
|
1450
1754
|
function isHtmlElement(el) {
|
|
1451
|
-
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
|
+
});
|
|
1452
1769
|
}
|
|
1453
1770
|
function setProp(el, key, val) {
|
|
1454
1771
|
el[key] = val;
|
|
1455
1772
|
}
|
|
1456
1773
|
function namespaceFor(el, name) {
|
|
1457
|
-
if (el.namespaceURI !==
|
|
1774
|
+
if (el.namespaceURI !== SVG_NS2) return null;
|
|
1458
1775
|
const lower = name.toLowerCase();
|
|
1459
1776
|
if (lower.startsWith("xlink:")) return XLINK_NS;
|
|
1460
1777
|
if (lower.startsWith("xml:")) return XML_NS;
|
|
1461
1778
|
return null;
|
|
1462
1779
|
}
|
|
1463
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) {
|
|
1464
1786
|
const ns = namespaceFor(el, name);
|
|
1465
1787
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
1466
1788
|
if (isEventHandlerAttr(name)) {
|
|
@@ -1473,6 +1795,14 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1473
1795
|
else el.removeAttribute(name);
|
|
1474
1796
|
return false;
|
|
1475
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
|
+
}
|
|
1476
1806
|
if (value == null) {
|
|
1477
1807
|
if (ns) el.removeAttributeNS(ns, localName);
|
|
1478
1808
|
else el.removeAttribute(name);
|
|
@@ -1516,7 +1846,12 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1516
1846
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
1517
1847
|
return true;
|
|
1518
1848
|
}
|
|
1519
|
-
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
|
+
}
|
|
1520
1855
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
1521
1856
|
if (current === safe) return true;
|
|
1522
1857
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -2020,7 +2355,7 @@ function forEachSubscriber(signal2, visit) {
|
|
|
2020
2355
|
}
|
|
2021
2356
|
|
|
2022
2357
|
// src/reactivity/track.ts
|
|
2023
|
-
var _runtimeVersion = true ? "4.
|
|
2358
|
+
var _runtimeVersion = true ? "4.8.0" : "dev";
|
|
2024
2359
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
2025
2360
|
function resolveReactiveApi() {
|
|
2026
2361
|
const g2 = globalThis;
|
|
@@ -2091,7 +2426,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
2091
2426
|
reportError(err, { phase: "binding", name: `bindAttribute("${attr}")`, node: el });
|
|
2092
2427
|
return;
|
|
2093
2428
|
}
|
|
2094
|
-
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")
|
|
2429
|
+
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")`, reactive: true });
|
|
2095
2430
|
}
|
|
2096
2431
|
return reactiveBinding2(commit, el);
|
|
2097
2432
|
}
|
|
@@ -2271,13 +2606,10 @@ function bindChildNode(placeholder, getter) {
|
|
|
2271
2606
|
}
|
|
2272
2607
|
|
|
2273
2608
|
// src/core/rendering/tagFactory.ts
|
|
2609
|
+
init_elementPolicy();
|
|
2274
2610
|
init_sanitize();
|
|
2275
2611
|
init_dispose();
|
|
2276
|
-
var
|
|
2277
|
-
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
2278
|
-
function isBlockedTag(tag) {
|
|
2279
|
-
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
2280
|
-
}
|
|
2612
|
+
var SVG_NS3 = "http://www.w3.org/2000/svg";
|
|
2281
2613
|
var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
2282
2614
|
"config",
|
|
2283
2615
|
"location",
|
|
@@ -2322,11 +2654,12 @@ function applyStyle(el, style2) {
|
|
|
2322
2654
|
}
|
|
2323
2655
|
const next = [];
|
|
2324
2656
|
for (const prop in value) {
|
|
2657
|
+
if (!Object.hasOwn(value, prop)) continue;
|
|
2325
2658
|
const val = value[prop];
|
|
2326
2659
|
if (val == null) continue;
|
|
2327
2660
|
const name = toKebab(prop);
|
|
2328
2661
|
next.push(name);
|
|
2329
|
-
decl.setProperty(name,
|
|
2662
|
+
decl.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
2330
2663
|
}
|
|
2331
2664
|
for (let i2 = 0; i2 < written.length; i2++) {
|
|
2332
2665
|
if (next.indexOf(written[i2]) === -1) decl.removeProperty(written[i2]);
|
|
@@ -2342,16 +2675,17 @@ function applyStyle(el, style2) {
|
|
|
2342
2675
|
}
|
|
2343
2676
|
const htmlEl = el;
|
|
2344
2677
|
for (const prop in style2) {
|
|
2678
|
+
if (!Object.hasOwn(style2, prop)) continue;
|
|
2345
2679
|
const val = style2[prop];
|
|
2346
2680
|
const name = toKebab(prop);
|
|
2347
2681
|
if (typeof val === "function") {
|
|
2348
2682
|
const getter = val;
|
|
2349
2683
|
const teardown = reactiveBinding2(() => {
|
|
2350
|
-
htmlEl.style.setProperty(name,
|
|
2684
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(getter()), { element: el }));
|
|
2351
2685
|
}, el);
|
|
2352
2686
|
registerDisposer(el, teardown);
|
|
2353
2687
|
} else {
|
|
2354
|
-
htmlEl.style.setProperty(name,
|
|
2688
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
2355
2689
|
}
|
|
2356
2690
|
}
|
|
2357
2691
|
}
|
|
@@ -2361,6 +2695,7 @@ function resolveClassValue(cls) {
|
|
|
2361
2695
|
if (!cls) return "";
|
|
2362
2696
|
let out = "";
|
|
2363
2697
|
for (const name in cls) {
|
|
2698
|
+
if (!Object.hasOwn(cls, name)) continue;
|
|
2364
2699
|
const val = cls[name];
|
|
2365
2700
|
const active = typeof val === "function" ? val() : val;
|
|
2366
2701
|
if (active) out = out ? `${out} ${name}` : name;
|
|
@@ -2385,6 +2720,7 @@ function applyClass(el, cls) {
|
|
|
2385
2720
|
let hasReactive = false;
|
|
2386
2721
|
let result = "";
|
|
2387
2722
|
for (const name in obj) {
|
|
2723
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
2388
2724
|
const val = obj[name];
|
|
2389
2725
|
if (typeof val === "function") {
|
|
2390
2726
|
hasReactive = true;
|
|
@@ -2396,6 +2732,7 @@ function applyClass(el, cls) {
|
|
|
2396
2732
|
const update = () => {
|
|
2397
2733
|
let r = "";
|
|
2398
2734
|
for (const name in obj) {
|
|
2735
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
2399
2736
|
const val = obj[name];
|
|
2400
2737
|
const active = typeof val === "function" ? val() : val;
|
|
2401
2738
|
if (active) r = r ? `${r} ${name}` : name;
|
|
@@ -2459,7 +2796,7 @@ function appendChildren(el, nodes) {
|
|
|
2459
2796
|
}
|
|
2460
2797
|
}
|
|
2461
2798
|
function tagFactory(tag, ns) {
|
|
2462
|
-
const blocked =
|
|
2799
|
+
const blocked = isBlockedElement(tag);
|
|
2463
2800
|
return (first, second) => {
|
|
2464
2801
|
if (blocked) {
|
|
2465
2802
|
throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
@@ -2522,6 +2859,7 @@ function tagFactory(tag, ns) {
|
|
|
2522
2859
|
const pOn = props.on;
|
|
2523
2860
|
if (pOn) {
|
|
2524
2861
|
for (const ev in pOn) {
|
|
2862
|
+
if (!Object.hasOwn(pOn, ev)) continue;
|
|
2525
2863
|
const handler = pOn[ev];
|
|
2526
2864
|
if (typeof handler === "function") {
|
|
2527
2865
|
el.addEventListener(ev, handler);
|
|
@@ -2548,6 +2886,7 @@ function tagFactory(tag, ns) {
|
|
|
2548
2886
|
continue;
|
|
2549
2887
|
// already handled above / below
|
|
2550
2888
|
default: {
|
|
2889
|
+
if (!Object.hasOwn(props, key)) continue;
|
|
2551
2890
|
const value = props[key];
|
|
2552
2891
|
if (value == null) continue;
|
|
2553
2892
|
if (isEventHandlerAttr(key)) continue;
|
|
@@ -2637,7 +2976,7 @@ var param = tagFactory("param");
|
|
|
2637
2976
|
var picture = tagFactory("picture");
|
|
2638
2977
|
var portal = tagFactory("portal");
|
|
2639
2978
|
var source = tagFactory("source");
|
|
2640
|
-
var svg = tagFactory("svg",
|
|
2979
|
+
var svg = tagFactory("svg", SVG_NS3);
|
|
2641
2980
|
var math = tagFactory("math");
|
|
2642
2981
|
var canvas = tagFactory("canvas");
|
|
2643
2982
|
var noscript = tagFactory("noscript");
|
|
@@ -2678,26 +3017,26 @@ var base = tagFactory("base");
|
|
|
2678
3017
|
var link = tagFactory("link");
|
|
2679
3018
|
var meta = tagFactory("meta");
|
|
2680
3019
|
var style = tagFactory("style");
|
|
2681
|
-
var circle = tagFactory("circle",
|
|
2682
|
-
var ellipse = tagFactory("ellipse",
|
|
2683
|
-
var g = tagFactory("g",
|
|
2684
|
-
var line = tagFactory("line",
|
|
2685
|
-
var path = tagFactory("path",
|
|
2686
|
-
var polygon = tagFactory("polygon",
|
|
2687
|
-
var polyline = tagFactory("polyline",
|
|
2688
|
-
var rect = tagFactory("rect",
|
|
2689
|
-
var text = tagFactory("text",
|
|
2690
|
-
var tspan = tagFactory("tspan",
|
|
2691
|
-
var defs = tagFactory("defs",
|
|
2692
|
-
var clipPath = tagFactory("clipPath",
|
|
2693
|
-
var mask = tagFactory("mask",
|
|
2694
|
-
var pattern = tagFactory("pattern",
|
|
2695
|
-
var linearGradient = tagFactory("linearGradient",
|
|
2696
|
-
var radialGradient = tagFactory("radialGradient",
|
|
2697
|
-
var stop = tagFactory("stop",
|
|
2698
|
-
var use = tagFactory("use",
|
|
2699
|
-
var symbol = tagFactory("symbol",
|
|
2700
|
-
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);
|
|
2701
3040
|
var center = tagFactory("center");
|
|
2702
3041
|
var font = tagFactory("font");
|
|
2703
3042
|
var marquee = tagFactory("marquee");
|
|
@@ -2880,6 +3219,7 @@ function getLocale() {
|
|
|
2880
3219
|
}
|
|
2881
3220
|
return clientLocale();
|
|
2882
3221
|
}
|
|
3222
|
+
_i18n.getLocale ?? (_i18n.getLocale = getLocale);
|
|
2883
3223
|
function registerTranslations(locale, messages) {
|
|
2884
3224
|
const prepared = { ...messages };
|
|
2885
3225
|
const merged = Object.assign(/* @__PURE__ */ Object.create(null), dictionaryFor(locale), prepared);
|
|
@@ -4593,15 +4933,7 @@ function RouterLink(props, children) {
|
|
|
4593
4933
|
const lkey = key.toLowerCase();
|
|
4594
4934
|
if (lkey === "href" || lkey[0] === "o" && lkey[1] === "n") return;
|
|
4595
4935
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4596
|
-
|
|
4597
|
-
if (isUrlAttribute(lkey)) {
|
|
4598
|
-
const safe = sanitizeUrl(str);
|
|
4599
|
-
if (safe) link2.setAttribute(key, safe);
|
|
4600
|
-
} else if (lkey === "style") {
|
|
4601
|
-
link2.setAttribute(key, sanitizeStyleAttribute(str, { element: link2 }));
|
|
4602
|
-
} else {
|
|
4603
|
-
link2.setAttribute(key, str);
|
|
4604
|
-
}
|
|
4936
|
+
setSafeAttribute(link2, key, String(value), { syncValueProperty: false, label: "RouterLink" });
|
|
4605
4937
|
}
|
|
4606
4938
|
});
|
|
4607
4939
|
if (content !== void 0) appendChildren(link2, content);
|
|
@@ -4900,14 +5232,7 @@ function createMemoryRouter(routes, _initialPath = "/") {
|
|
|
4900
5232
|
|
|
4901
5233
|
// src/plugins/routerSSR.ts
|
|
4902
5234
|
init_ssr();
|
|
4903
|
-
|
|
4904
|
-
// src/utils/guards.ts
|
|
4905
|
-
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
4906
|
-
function isUnsafeKey(key) {
|
|
4907
|
-
return UNSAFE_KEYS.has(key);
|
|
4908
|
-
}
|
|
4909
|
-
|
|
4910
|
-
// src/plugins/routerSSR.ts
|
|
5235
|
+
init_guards();
|
|
4911
5236
|
init_headEntry();
|
|
4912
5237
|
init_sanitize();
|
|
4913
5238
|
function safeDecode(raw) {
|
|
@@ -5140,8 +5465,7 @@ function serializeRouteState(state2, nonce) {
|
|
|
5140
5465
|
return `<script${nonceAttr}>window.${SSR_ROUTE_STATE_KEY}=${json}</script>`;
|
|
5141
5466
|
}
|
|
5142
5467
|
function deserializeRouteState() {
|
|
5143
|
-
|
|
5144
|
-
return window[SSR_ROUTE_STATE_KEY];
|
|
5468
|
+
return readOwnGlobal(SSR_ROUTE_STATE_KEY);
|
|
5145
5469
|
}
|
|
5146
5470
|
function hydrateRouter(routes, options) {
|
|
5147
5471
|
const serverState = deserializeRouteState();
|
|
@@ -5581,7 +5905,7 @@ var CDN_ENTRY_POINTS = {
|
|
|
5581
5905
|
};
|
|
5582
5906
|
var packageInfo = {
|
|
5583
5907
|
name: "sibujs",
|
|
5584
|
-
version: true ? "4.
|
|
5908
|
+
version: true ? "4.8.0" : "dev",
|
|
5585
5909
|
entryPoints: MODULE_ENTRY_POINTS,
|
|
5586
5910
|
/**
|
|
5587
5911
|
* Generate the package.json `exports` map. Module entries resolve to the
|
|
@@ -5726,7 +6050,7 @@ var env = {
|
|
|
5726
6050
|
};
|
|
5727
6051
|
|
|
5728
6052
|
// src/plugins/versioning.ts
|
|
5729
|
-
var VERSION = true ? "4.
|
|
6053
|
+
var VERSION = true ? "4.8.0" : "dev";
|
|
5730
6054
|
var NUM = "(?:0|[1-9]\\d*)";
|
|
5731
6055
|
var PRE_ID = `(?:${NUM}|\\d*[a-zA-Z-][0-9a-zA-Z-]*)`;
|
|
5732
6056
|
var BUILD_ID = "[0-9a-zA-Z-]+";
|
|
@@ -6008,15 +6332,18 @@ function extractRangeTarget(range) {
|
|
|
6008
6332
|
// src/plugins/startup.ts
|
|
6009
6333
|
init_errors();
|
|
6010
6334
|
init_ssr();
|
|
6335
|
+
init_sanitize();
|
|
6011
6336
|
function preloadCritical(resources) {
|
|
6012
6337
|
if (typeof document === "undefined") return;
|
|
6013
6338
|
for (const resource of resources) {
|
|
6014
|
-
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, "\\$&");
|
|
6015
6342
|
const existing = document.querySelector(`link[rel="preload"][href="${safeHref}"]`);
|
|
6016
6343
|
if (existing) continue;
|
|
6017
6344
|
const link2 = document.createElement("link");
|
|
6018
6345
|
link2.rel = "preload";
|
|
6019
|
-
link2.href =
|
|
6346
|
+
link2.href = href;
|
|
6020
6347
|
link2.setAttribute("as", resource.as);
|
|
6021
6348
|
if (resource.type) {
|
|
6022
6349
|
link2.type = resource.type;
|