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/index.cjs
CHANGED
|
@@ -28,8 +28,9 @@ __export(index_exports, {
|
|
|
28
28
|
Loading: () => Loading,
|
|
29
29
|
MAX_DRAIN_TEARDOWNS: () => MAX_DRAIN_TEARDOWNS,
|
|
30
30
|
Portal: () => Portal,
|
|
31
|
-
SVG_NS: () =>
|
|
31
|
+
SVG_NS: () => SVG_NS3,
|
|
32
32
|
Suspense: () => Suspense,
|
|
33
|
+
__renderParsedTemplate: () => __renderParsedTemplate,
|
|
33
34
|
__resetIdCounter: () => __resetIdCounter,
|
|
34
35
|
a: () => a,
|
|
35
36
|
abbr: () => abbr,
|
|
@@ -411,6 +412,49 @@ function registerDisposer(node, teardown) {
|
|
|
411
412
|
const capture = resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
|
|
412
413
|
if (capture) capture.entries.push([node, teardown]);
|
|
413
414
|
}
|
|
415
|
+
function withDisposerRollback(build) {
|
|
416
|
+
const frame = { entries: [], closed: false };
|
|
417
|
+
const captured = frame.entries;
|
|
418
|
+
registrationCaptures.push(frame);
|
|
419
|
+
let result;
|
|
420
|
+
try {
|
|
421
|
+
result = build();
|
|
422
|
+
} catch (err) {
|
|
423
|
+
let executed = 0;
|
|
424
|
+
try {
|
|
425
|
+
while (captured.length > 0) {
|
|
426
|
+
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
427
|
+
reportDrainRunaway("rollback", executed, captured.length);
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
const [node, teardown] = captured.pop();
|
|
431
|
+
if (!unregisterDisposer(node, teardown)) continue;
|
|
432
|
+
executed++;
|
|
433
|
+
try {
|
|
434
|
+
teardown();
|
|
435
|
+
} catch (cleanupErr) {
|
|
436
|
+
reportError(cleanupErr, { phase: "cleanup", name: "disposer" });
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
} finally {
|
|
440
|
+
frame.closed = true;
|
|
441
|
+
captured.length = 0;
|
|
442
|
+
registrationCaptures.pop();
|
|
443
|
+
}
|
|
444
|
+
throw err;
|
|
445
|
+
}
|
|
446
|
+
frame.closed = true;
|
|
447
|
+
registrationCaptures.pop();
|
|
448
|
+
const parent = resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
|
|
449
|
+
if (parent) {
|
|
450
|
+
for (const entry of captured) {
|
|
451
|
+
if (elementDisposers.get(entry[0])?.includes(entry[1])) parent.entries.push(entry);
|
|
452
|
+
}
|
|
453
|
+
frame.forwardTo = parent;
|
|
454
|
+
}
|
|
455
|
+
captured.length = 0;
|
|
456
|
+
return result;
|
|
457
|
+
}
|
|
414
458
|
function unregisterDisposer(node, teardown) {
|
|
415
459
|
const disposers = elementDisposers.get(node);
|
|
416
460
|
if (!disposers) return false;
|
|
@@ -490,6 +534,11 @@ function checkLeaks(warnThreshold = 0) {
|
|
|
490
534
|
function stripControlChars(value) {
|
|
491
535
|
return value.replace(/[\x00-\x20\x7f-\x9f]+/g, "");
|
|
492
536
|
}
|
|
537
|
+
var ASCII_UPPER = /[A-Z]/;
|
|
538
|
+
var ASCII_UPPER_G = /[A-Z]/g;
|
|
539
|
+
function canonicalAttrName(name) {
|
|
540
|
+
return ASCII_UPPER.test(name) ? name.replace(ASCII_UPPER_G, (ch) => String.fromCharCode(ch.charCodeAt(0) + 32)) : name;
|
|
541
|
+
}
|
|
493
542
|
function isEventHandlerAttr(name) {
|
|
494
543
|
if (name.length < 3) return false;
|
|
495
544
|
const lower = name.toLowerCase();
|
|
@@ -501,6 +550,9 @@ function sanitizeUrl(url) {
|
|
|
501
550
|
const probe = stripControlChars(url).trim();
|
|
502
551
|
if (!probe) return "";
|
|
503
552
|
const output2 = url.replace(OUTER_TRIM, "");
|
|
553
|
+
if (probe.length >= 2 && (probe[0] === "\\" || probe[0] === "/") && (probe[1] === "\\" || probe[1] === "/") && (probe[0] === "\\" || probe[1] === "\\")) {
|
|
554
|
+
return "";
|
|
555
|
+
}
|
|
504
556
|
const lower = probe.toLowerCase();
|
|
505
557
|
let schemeEnd = -1;
|
|
506
558
|
for (let i2 = 0; i2 < lower.length; i2++) {
|
|
@@ -517,19 +569,58 @@ function sanitizeUrl(url) {
|
|
|
517
569
|
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
518
570
|
return output2;
|
|
519
571
|
}
|
|
520
|
-
var SRCSET_DESCRIPTOR = /^\
|
|
572
|
+
var SRCSET_DESCRIPTOR = /^\d+(\.\d+)?[wx]$/;
|
|
573
|
+
function isSrcsetWhitespace(ch) {
|
|
574
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
575
|
+
}
|
|
521
576
|
function sanitizeSrcset(value) {
|
|
522
|
-
const
|
|
577
|
+
const input2 = String(value);
|
|
523
578
|
const out = [];
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
if (
|
|
529
|
-
|
|
530
|
-
|
|
579
|
+
let i2 = 0;
|
|
580
|
+
const n = input2.length;
|
|
581
|
+
while (i2 < n) {
|
|
582
|
+
while (i2 < n && (isSrcsetWhitespace(input2[i2]) || input2[i2] === ",")) i2++;
|
|
583
|
+
if (i2 >= n) break;
|
|
584
|
+
const urlStart = i2;
|
|
585
|
+
while (i2 < n && !isSrcsetWhitespace(input2[i2])) i2++;
|
|
586
|
+
let url = input2.slice(urlStart, i2);
|
|
587
|
+
const descriptors = [];
|
|
588
|
+
if (url.endsWith(",")) {
|
|
589
|
+
url = url.replace(/,+$/, "");
|
|
590
|
+
} else {
|
|
591
|
+
let current = "";
|
|
592
|
+
let inParens = false;
|
|
593
|
+
while (i2 < n) {
|
|
594
|
+
const ch = input2[i2];
|
|
595
|
+
if (inParens) {
|
|
596
|
+
current += ch;
|
|
597
|
+
if (ch === ")") inParens = false;
|
|
598
|
+
i2++;
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
if (isSrcsetWhitespace(ch)) {
|
|
602
|
+
if (current) descriptors.push(current);
|
|
603
|
+
current = "";
|
|
604
|
+
i2++;
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
if (ch === ",") {
|
|
608
|
+
i2++;
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
if (ch === "(") inParens = true;
|
|
612
|
+
current += ch;
|
|
613
|
+
i2++;
|
|
614
|
+
}
|
|
615
|
+
if (current) descriptors.push(current);
|
|
616
|
+
}
|
|
617
|
+
if (url === "") continue;
|
|
618
|
+
if (descriptors.length > 1) continue;
|
|
619
|
+
if (descriptors.length === 1 && !SRCSET_DESCRIPTOR.test(descriptors[0])) continue;
|
|
620
|
+
const safe = sanitizeUrl(url);
|
|
531
621
|
if (!safe) continue;
|
|
532
|
-
|
|
622
|
+
if (safe.startsWith(",") || safe.endsWith(",")) continue;
|
|
623
|
+
out.push(descriptors.length === 1 ? `${safe} ${descriptors[0]}` : safe);
|
|
533
624
|
}
|
|
534
625
|
return out.join(", ");
|
|
535
626
|
}
|
|
@@ -588,8 +679,16 @@ var BLOCKED_CSS_NEEDLES = [
|
|
|
588
679
|
"behavior:",
|
|
589
680
|
"@import",
|
|
590
681
|
"image-set(",
|
|
591
|
-
"filter:progid"
|
|
682
|
+
"filter:progid",
|
|
683
|
+
// CSS Images 4 `image("…")` and CSS Values 5 `src("…")` take a URL as a
|
|
684
|
+
// plain STRING, so they fetch without ever spelling `url(`. Support is thin
|
|
685
|
+
// today, which is exactly when a blocklist should get ahead of it.
|
|
686
|
+
"image(",
|
|
687
|
+
"src("
|
|
592
688
|
];
|
|
689
|
+
var CSS_REASON_MOZ_BINDING = 4;
|
|
690
|
+
var CSS_REASON_BEHAVIOR = 5;
|
|
691
|
+
var CSS_REASON_PROGID = 8;
|
|
593
692
|
function describeElement(el) {
|
|
594
693
|
if (!el) return "an element";
|
|
595
694
|
let out = el.tagName.toLowerCase();
|
|
@@ -613,7 +712,9 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
613
712
|
"behavior: loads and runs a remote HTC script",
|
|
614
713
|
"@import pulls in a remote stylesheet",
|
|
615
714
|
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
616
|
-
"filter:progid activates legacy scriptable filters"
|
|
715
|
+
"filter:progid activates legacy scriptable filters",
|
|
716
|
+
"image() fetches its string argument as a URL, the same exfiltration channel as url()",
|
|
717
|
+
"src() fetches its string argument as a URL, the same exfiltration channel as url()"
|
|
617
718
|
];
|
|
618
719
|
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
619
720
|
const where = describeElement(ctx?.element);
|
|
@@ -628,27 +729,110 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
628
729
|
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.`;
|
|
629
730
|
});
|
|
630
731
|
}
|
|
732
|
+
function normalizeCssForScan(value) {
|
|
733
|
+
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
734
|
+
return normalized.toLowerCase().replace(/\s+/g, "");
|
|
735
|
+
}
|
|
631
736
|
function blockedCssReason(value) {
|
|
632
737
|
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
633
|
-
const
|
|
634
|
-
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
738
|
+
const lower = normalizeCssForScan(value);
|
|
635
739
|
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
636
740
|
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
637
741
|
}
|
|
638
742
|
return -1;
|
|
639
743
|
}
|
|
640
|
-
function
|
|
641
|
-
const reason =
|
|
744
|
+
function sanitizeCSSDeclaration(property, value, context2) {
|
|
745
|
+
const reason = blockedDeclarationReason(property, value);
|
|
642
746
|
if (reason === -1) return value;
|
|
643
|
-
warnDroppedDeclaration(value, reason, context2);
|
|
747
|
+
warnDroppedDeclaration(value, reason, { property, element: context2?.element });
|
|
644
748
|
return "";
|
|
645
749
|
}
|
|
750
|
+
function blockedDeclarationReason(property, value) {
|
|
751
|
+
const reason = blockedCssReason(value);
|
|
752
|
+
if (reason !== -1) return reason;
|
|
753
|
+
const name = canonicalAttrName(property);
|
|
754
|
+
if (name === "behavior") return CSS_REASON_BEHAVIOR;
|
|
755
|
+
if (name === "-moz-binding") return CSS_REASON_MOZ_BINDING;
|
|
756
|
+
if ((name === "filter" || name === "-ms-filter") && normalizeCssForScan(value).includes("progid:")) {
|
|
757
|
+
return CSS_REASON_PROGID;
|
|
758
|
+
}
|
|
759
|
+
return -1;
|
|
760
|
+
}
|
|
761
|
+
function parseStyleDeclarations(css) {
|
|
762
|
+
const chunks = [];
|
|
763
|
+
let buf = "";
|
|
764
|
+
let depth = 0;
|
|
765
|
+
let quote2 = "";
|
|
766
|
+
for (let i2 = 0; i2 < css.length; i2++) {
|
|
767
|
+
const ch = css[i2];
|
|
768
|
+
if (quote2) {
|
|
769
|
+
buf += ch;
|
|
770
|
+
if (ch === "\\" && i2 + 1 < css.length) buf += css[++i2];
|
|
771
|
+
else if (ch === quote2) quote2 = "";
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
if (ch === "\\") {
|
|
775
|
+
buf += ch;
|
|
776
|
+
if (i2 + 1 < css.length) buf += css[++i2];
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
if (ch === "/" && css[i2 + 1] === "*") {
|
|
780
|
+
const end = css.indexOf("*/", i2 + 2);
|
|
781
|
+
if (end === -1) return null;
|
|
782
|
+
i2 = end + 1;
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
if (ch === '"' || ch === "'") quote2 = ch;
|
|
786
|
+
else if (ch === "(" || ch === "[") depth++;
|
|
787
|
+
else if (ch === ")" || ch === "]") {
|
|
788
|
+
if (--depth < 0) return null;
|
|
789
|
+
} else if (ch === "{" || ch === "}") return null;
|
|
790
|
+
else if (ch === ";" && depth === 0) {
|
|
791
|
+
chunks.push(buf);
|
|
792
|
+
buf = "";
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
buf += ch;
|
|
796
|
+
}
|
|
797
|
+
if (quote2 || depth !== 0) return null;
|
|
798
|
+
chunks.push(buf);
|
|
799
|
+
const out = [];
|
|
800
|
+
for (const chunk of chunks) {
|
|
801
|
+
const colon = chunk.indexOf(":");
|
|
802
|
+
if (colon === -1) continue;
|
|
803
|
+
const rawName = chunk.slice(0, colon).trim();
|
|
804
|
+
if (!/^(--[\w-]+|-?[a-zA-Z_][\w-]*)$/.test(rawName)) continue;
|
|
805
|
+
let value = chunk.slice(colon + 1).trim();
|
|
806
|
+
const bang = /!\s*important\s*$/i.exec(value);
|
|
807
|
+
if (bang) value = value.slice(0, bang.index).trim();
|
|
808
|
+
if (value === "") continue;
|
|
809
|
+
const property = rawName.startsWith("--") ? rawName : canonicalAttrName(rawName);
|
|
810
|
+
out.push([property, value, bang !== null]);
|
|
811
|
+
}
|
|
812
|
+
return out;
|
|
813
|
+
}
|
|
814
|
+
function sanitizeStyleDeclarationList(cssText, context2) {
|
|
815
|
+
const input2 = String(cssText);
|
|
816
|
+
const declarations = parseStyleDeclarations(input2);
|
|
817
|
+
if (declarations === null) {
|
|
818
|
+
if (blockedCssReason(input2) !== -1) warnDroppedDeclaration(input2, blockedCssReason(input2), context2);
|
|
819
|
+
return "";
|
|
820
|
+
}
|
|
821
|
+
const kept = [];
|
|
822
|
+
for (const [property, value, important] of declarations) {
|
|
823
|
+
const reason = blockedDeclarationReason(property, value);
|
|
824
|
+
if (reason !== -1) {
|
|
825
|
+
warnDroppedDeclaration(value, reason, { property, element: context2?.element });
|
|
826
|
+
continue;
|
|
827
|
+
}
|
|
828
|
+
kept.push(`${property}: ${value}${important ? " !important" : ""}`);
|
|
829
|
+
}
|
|
830
|
+
return kept.join("; ");
|
|
831
|
+
}
|
|
646
832
|
function sanitizeStyleAttribute(cssText, context2) {
|
|
647
833
|
const input2 = String(cssText);
|
|
648
834
|
if (input2.trim() === "") return "";
|
|
649
|
-
if (typeof document === "undefined")
|
|
650
|
-
return sanitizeCSSValue(input2, context2) === "" ? "" : input2;
|
|
651
|
-
}
|
|
835
|
+
if (typeof document === "undefined") return sanitizeStyleDeclarationList(input2, context2);
|
|
652
836
|
const probe = document.createElement("div");
|
|
653
837
|
try {
|
|
654
838
|
probe.style.cssText = input2;
|
|
@@ -659,8 +843,7 @@ function sanitizeStyleAttribute(cssText, context2) {
|
|
|
659
843
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
660
844
|
const property = probe.style[i2];
|
|
661
845
|
const value = probe.style.getPropertyValue(property);
|
|
662
|
-
|
|
663
|
-
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
846
|
+
const reason = blockedDeclarationReason(property, value);
|
|
664
847
|
if (reason !== -1) {
|
|
665
848
|
warnDroppedDeclaration(value, reason, { property, element: context2?.element });
|
|
666
849
|
continue;
|
|
@@ -692,6 +875,13 @@ var HTML_CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set(["srcdoc"]);
|
|
|
692
875
|
function isHtmlContentAttribute(name) {
|
|
693
876
|
return HTML_CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
694
877
|
}
|
|
878
|
+
function isUrlAttribute(attr) {
|
|
879
|
+
return URL_ATTRIBUTES.has(attr.toLowerCase());
|
|
880
|
+
}
|
|
881
|
+
function isPolicyAttribute(name) {
|
|
882
|
+
const lower = name.toLowerCase();
|
|
883
|
+
return lower === "style" || URL_ATTRIBUTES.has(lower);
|
|
884
|
+
}
|
|
695
885
|
function sanitizeAttributeString(attr, value, context2) {
|
|
696
886
|
const lower = attr.toLowerCase();
|
|
697
887
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
@@ -699,27 +889,233 @@ function sanitizeAttributeString(attr, value, context2) {
|
|
|
699
889
|
if (lower === "style") return sanitizeStyleAttribute(value, context2);
|
|
700
890
|
return value;
|
|
701
891
|
}
|
|
892
|
+
function resolveAttributeValue(attr, value, context2) {
|
|
893
|
+
if (!isPolicyAttribute(attr)) return value;
|
|
894
|
+
const safe = sanitizeAttributeString(attr, value, context2);
|
|
895
|
+
return safe === "" ? null : safe;
|
|
896
|
+
}
|
|
702
897
|
|
|
703
|
-
// src/utils/
|
|
898
|
+
// src/utils/metaRefresh.ts
|
|
899
|
+
function isAsciiWhitespace(ch) {
|
|
900
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
901
|
+
}
|
|
902
|
+
function trimAsciiWhitespace(value) {
|
|
903
|
+
let start = 0;
|
|
904
|
+
let end = value.length;
|
|
905
|
+
while (start < end && isAsciiWhitespace(value[start])) start++;
|
|
906
|
+
while (end > start && isAsciiWhitespace(value[end - 1])) end--;
|
|
907
|
+
return value.slice(start, end);
|
|
908
|
+
}
|
|
909
|
+
var forbidden = (reason) => ({ kind: "forbidden", reason });
|
|
910
|
+
function parseMetaRefreshContent(content) {
|
|
911
|
+
const raw = trimAsciiWhitespace(stripControlChars(content));
|
|
912
|
+
if (raw === "") return forbidden(DEV ? "empty content" : "");
|
|
913
|
+
let i2 = 0;
|
|
914
|
+
while (i2 < raw.length && raw[i2] >= "0" && raw[i2] <= "9") i2++;
|
|
915
|
+
if (i2 === 0) return forbidden(DEV ? "missing or non-numeric delay" : "");
|
|
916
|
+
const delay = Number.parseInt(raw.slice(0, i2), 10);
|
|
917
|
+
if (!Number.isFinite(delay)) return forbidden(DEV ? "unparseable delay" : "");
|
|
918
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
919
|
+
if (i2 === raw.length) return { kind: "delay-only", delay };
|
|
920
|
+
if (raw[i2] !== ";" && raw[i2] !== ",") return forbidden(DEV ? "unexpected text after delay" : "");
|
|
921
|
+
i2++;
|
|
922
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
923
|
+
const keyStart = i2;
|
|
924
|
+
while (i2 < raw.length && !isAsciiWhitespace(raw[i2]) && raw[i2] !== "=") i2++;
|
|
925
|
+
const key = raw.slice(keyStart, i2).toLowerCase();
|
|
926
|
+
if (key !== "url") return forbidden(DEV ? `unsupported refresh key ${JSON.stringify(key)}` : "");
|
|
927
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
928
|
+
if (raw[i2] !== "=") return forbidden(DEV ? "missing '=' after url" : "");
|
|
929
|
+
i2++;
|
|
930
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
931
|
+
let destination;
|
|
932
|
+
const quote2 = raw[i2];
|
|
933
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
934
|
+
const close = raw.indexOf(quote2, i2 + 1);
|
|
935
|
+
if (close === -1) return forbidden(DEV ? "unterminated quoted destination" : "");
|
|
936
|
+
destination = raw.slice(i2 + 1, close);
|
|
937
|
+
const rest = trimAsciiWhitespace(raw.slice(close + 1));
|
|
938
|
+
if (rest !== "") return forbidden(DEV ? "trailing text after quoted destination" : "");
|
|
939
|
+
} else {
|
|
940
|
+
destination = trimAsciiWhitespace(raw.slice(i2));
|
|
941
|
+
if (/[;,]/.test(destination)) return forbidden(DEV ? "multiple refresh assignments" : "");
|
|
942
|
+
}
|
|
943
|
+
if (destination === "") return forbidden(DEV ? "empty destination" : "");
|
|
944
|
+
const sanitizedDestination = sanitizeUrl(destination);
|
|
945
|
+
if (sanitizedDestination === "") return forbidden(DEV ? "destination uses a disallowed protocol" : "");
|
|
946
|
+
return { kind: "allowed", delay, destination, sanitizedDestination };
|
|
947
|
+
}
|
|
948
|
+
function resolveMetaRefreshPolicy(attributes) {
|
|
949
|
+
let httpEquiv;
|
|
950
|
+
let content;
|
|
951
|
+
let duplicateName;
|
|
952
|
+
const seen = /* @__PURE__ */ new Set();
|
|
953
|
+
for (const [key, value] of attributes) {
|
|
954
|
+
const canonical = canonicalAttrName(key);
|
|
955
|
+
if (seen.has(canonical)) duplicateName = canonical;
|
|
956
|
+
seen.add(canonical);
|
|
957
|
+
if (canonical === "http-equiv") httpEquiv = value;
|
|
958
|
+
else if (canonical === "content") content = value;
|
|
959
|
+
}
|
|
960
|
+
if (duplicateName !== void 0) {
|
|
961
|
+
return forbidden(DEV ? `duplicate case-insensitive attribute ${JSON.stringify(duplicateName)}` : "");
|
|
962
|
+
}
|
|
963
|
+
if (typeof httpEquiv !== "string") return { kind: "not-refresh" };
|
|
964
|
+
if (trimAsciiWhitespace(stripControlChars(httpEquiv)).toLowerCase() !== "refresh") {
|
|
965
|
+
return { kind: "not-refresh" };
|
|
966
|
+
}
|
|
967
|
+
if (typeof content !== "string") return { kind: "not-refresh" };
|
|
968
|
+
return parseMetaRefreshContent(content);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// src/utils/elementPolicy.ts
|
|
704
972
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
705
973
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
974
|
+
var BLOCKED_ELEMENTS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
975
|
+
function canonicalTagName(tag) {
|
|
976
|
+
return canonicalAttrName(tag);
|
|
977
|
+
}
|
|
978
|
+
function isBlockedElement(tag) {
|
|
979
|
+
return BLOCKED_ELEMENTS.has(canonicalTagName(tag));
|
|
980
|
+
}
|
|
981
|
+
var CODE_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
982
|
+
function isCodeTextElement(tag) {
|
|
983
|
+
return CODE_TEXT_ELEMENTS.has(canonicalTagName(tag));
|
|
984
|
+
}
|
|
985
|
+
var ContextualRefusal = {
|
|
986
|
+
None: 0,
|
|
987
|
+
/** The element would carry a refresh directive the shared policy forbids. */
|
|
988
|
+
MetaRefreshForbidden: 1,
|
|
989
|
+
/** A `<meta>` with a reactive binding may not carry any refresh directive. */
|
|
990
|
+
MetaRefreshReactive: 2,
|
|
991
|
+
/** A runtime value may not choose which program a `<script>` runs. */
|
|
992
|
+
ScriptSource: 3,
|
|
993
|
+
/** An SVG animation may not target a URL, handler or document attribute. */
|
|
994
|
+
AnimationTarget: 4,
|
|
995
|
+
/** A runtime-written `href` may not become an applied stylesheet. */
|
|
996
|
+
StylesheetSource: 5
|
|
997
|
+
};
|
|
998
|
+
var SCRIPT_SOURCE_ATTRIBUTES = /* @__PURE__ */ new Set(["src", "href", "xlink:href", "type", "language"]);
|
|
999
|
+
var SVG_ANIMATION_ELEMENTS = /* @__PURE__ */ new Set(["animate", "set", "animateMotion", "animateTransform", "animateColor"]);
|
|
1000
|
+
var reactiveMetaElements = /* @__PURE__ */ new WeakSet();
|
|
1001
|
+
function isHtmlNamespace(el) {
|
|
1002
|
+
return el.namespaceURI === HTML_NS || el.namespaceURI === null;
|
|
1003
|
+
}
|
|
1004
|
+
function metaSnapshot(el, canonical, value) {
|
|
1005
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
1006
|
+
const attrs = el.attributes;
|
|
1007
|
+
for (let i2 = 0; i2 < attrs.length; i2++) {
|
|
1008
|
+
const attr = attrs[i2];
|
|
1009
|
+
if (attr.name === canonical) continue;
|
|
1010
|
+
snapshot.set(attr.name, attr.value);
|
|
1011
|
+
}
|
|
1012
|
+
if (canonical !== null && value !== null) snapshot.set(canonical, value);
|
|
1013
|
+
return snapshot;
|
|
1014
|
+
}
|
|
1015
|
+
function claimReactiveMeta(el) {
|
|
1016
|
+
if (reactiveMetaElements.has(el)) return;
|
|
1017
|
+
reactiveMetaElements.add(el);
|
|
1018
|
+
if (el.getAttribute("content") === null) return;
|
|
1019
|
+
if (resolveMetaRefreshPolicy(metaSnapshot(el, null, null)).kind !== "not-refresh") {
|
|
1020
|
+
el.removeAttribute("content");
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
function metaRefusal(el, name, value, origin) {
|
|
1024
|
+
if (!isHtmlNamespace(el)) return ContextualRefusal.None;
|
|
1025
|
+
const canonical = canonicalAttrName(name);
|
|
1026
|
+
if (canonical !== "http-equiv" && canonical !== "content") return ContextualRefusal.None;
|
|
1027
|
+
if (origin === "reactive") claimReactiveMeta(el);
|
|
1028
|
+
if (value === null) return ContextualRefusal.None;
|
|
1029
|
+
if (canonical === "content" && !el.hasAttribute("http-equiv")) return ContextualRefusal.None;
|
|
1030
|
+
const decision = resolveMetaRefreshPolicy(metaSnapshot(el, canonical, value));
|
|
1031
|
+
if (decision.kind === "forbidden") return ContextualRefusal.MetaRefreshForbidden;
|
|
1032
|
+
if (decision.kind !== "not-refresh" && reactiveMetaElements.has(el)) return ContextualRefusal.MetaRefreshReactive;
|
|
1033
|
+
return ContextualRefusal.None;
|
|
1034
|
+
}
|
|
1035
|
+
function animationRefusal(name, value) {
|
|
1036
|
+
if (value === null || canonicalAttrName(name) !== "attributename") return ContextualRefusal.None;
|
|
1037
|
+
const target = stripControlChars(value);
|
|
1038
|
+
return isUrlAttribute(target) || isEventHandlerAttr(target) || isHtmlContentAttribute(target) ? ContextualRefusal.AnimationTarget : ContextualRefusal.None;
|
|
1039
|
+
}
|
|
1040
|
+
var runtimeHrefLinks = /* @__PURE__ */ new WeakSet();
|
|
1041
|
+
function relHasStylesheet(rel) {
|
|
1042
|
+
if (rel === null) return false;
|
|
1043
|
+
const lower = canonicalAttrName(rel);
|
|
1044
|
+
if (!lower.includes("stylesheet")) return false;
|
|
1045
|
+
const tokens = lower.split(/[\t\n\f\r ]+/);
|
|
1046
|
+
for (let i2 = 0; i2 < tokens.length; i2++) if (tokens[i2] === "stylesheet") return true;
|
|
1047
|
+
return false;
|
|
1048
|
+
}
|
|
1049
|
+
function stylesheetRefusal(el, name, value, origin) {
|
|
1050
|
+
if (!isHtmlNamespace(el)) return ContextualRefusal.None;
|
|
1051
|
+
const canonical = canonicalAttrName(name);
|
|
1052
|
+
if (canonical === "href") {
|
|
1053
|
+
if (origin === "static" || value === null) return ContextualRefusal.None;
|
|
1054
|
+
if (relHasStylesheet(el.getAttribute("rel"))) return ContextualRefusal.StylesheetSource;
|
|
1055
|
+
runtimeHrefLinks.add(el);
|
|
1056
|
+
return ContextualRefusal.None;
|
|
1057
|
+
}
|
|
1058
|
+
if (canonical === "rel") {
|
|
1059
|
+
if (!relHasStylesheet(value)) return ContextualRefusal.None;
|
|
1060
|
+
return runtimeHrefLinks.has(el) && el.hasAttribute("href") ? ContextualRefusal.StylesheetSource : ContextualRefusal.None;
|
|
1061
|
+
}
|
|
1062
|
+
return ContextualRefusal.None;
|
|
1063
|
+
}
|
|
1064
|
+
function contextualAttributeRefusal(el, name, value, origin) {
|
|
1065
|
+
const local = el.localName;
|
|
1066
|
+
if (local === "meta") return metaRefusal(el, name, value, origin);
|
|
1067
|
+
if (local === "link") return stylesheetRefusal(el, name, value, origin);
|
|
1068
|
+
if (local === "script") {
|
|
1069
|
+
if (origin === "static" || value === null) return ContextualRefusal.None;
|
|
1070
|
+
return SCRIPT_SOURCE_ATTRIBUTES.has(canonicalAttrName(name)) ? ContextualRefusal.ScriptSource : ContextualRefusal.None;
|
|
1071
|
+
}
|
|
1072
|
+
if (SVG_ANIMATION_ELEMENTS.has(local) && el.namespaceURI === SVG_NS) return animationRefusal(name, value);
|
|
1073
|
+
return ContextualRefusal.None;
|
|
1074
|
+
}
|
|
1075
|
+
function settleAttributeProvenance(el, name, origin) {
|
|
1076
|
+
if (el.localName !== "link" || canonicalAttrName(name) !== "href") return;
|
|
1077
|
+
if (origin !== "static" && el.hasAttribute("href")) runtimeHrefLinks.add(el);
|
|
1078
|
+
else runtimeHrefLinks.delete(el);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// src/utils/setSafeAttribute.ts
|
|
1082
|
+
var HTML_NS2 = "http://www.w3.org/1999/xhtml";
|
|
1083
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
706
1084
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
707
1085
|
var XML_NS = "http://www.w3.org/XML/1998/namespace";
|
|
708
1086
|
var BOOLEAN_IDL_ATTRS = /* @__PURE__ */ new Set(["checked", "disabled", "selected"]);
|
|
709
1087
|
function isHtmlElement(el) {
|
|
710
|
-
return el.namespaceURI === null || el.namespaceURI ===
|
|
1088
|
+
return el.namespaceURI === null || el.namespaceURI === HTML_NS2;
|
|
1089
|
+
}
|
|
1090
|
+
function warnContextualRefusal(label2, name, refusal) {
|
|
1091
|
+
devWarnLazy(() => {
|
|
1092
|
+
const reasons = [
|
|
1093
|
+
"",
|
|
1094
|
+
'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)',
|
|
1095
|
+
"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",
|
|
1096
|
+
"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",
|
|
1097
|
+
"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",
|
|
1098
|
+
'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'
|
|
1099
|
+
];
|
|
1100
|
+
return `${label2}: refusing "${name}" in this element's context \u2014 ${reasons[refusal]}. The write was not performed.`;
|
|
1101
|
+
});
|
|
711
1102
|
}
|
|
712
1103
|
function setProp(el, key, val) {
|
|
713
1104
|
el[key] = val;
|
|
714
1105
|
}
|
|
715
1106
|
function namespaceFor(el, name) {
|
|
716
|
-
if (el.namespaceURI !==
|
|
1107
|
+
if (el.namespaceURI !== SVG_NS2) return null;
|
|
717
1108
|
const lower = name.toLowerCase();
|
|
718
1109
|
if (lower.startsWith("xlink:")) return XLINK_NS;
|
|
719
1110
|
if (lower.startsWith("xml:")) return XML_NS;
|
|
720
1111
|
return null;
|
|
721
1112
|
}
|
|
722
1113
|
function setSafeAttribute(el, name, value, options = {}) {
|
|
1114
|
+
const written = commitSafeAttribute(el, name, value, options);
|
|
1115
|
+
if (el.localName === "link") settleAttributeProvenance(el, name, options.reactive ? "reactive" : "runtime");
|
|
1116
|
+
return written;
|
|
1117
|
+
}
|
|
1118
|
+
function commitSafeAttribute(el, name, value, options) {
|
|
723
1119
|
const ns = namespaceFor(el, name);
|
|
724
1120
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
725
1121
|
if (isEventHandlerAttr(name)) {
|
|
@@ -732,6 +1128,14 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
732
1128
|
else el.removeAttribute(name);
|
|
733
1129
|
return false;
|
|
734
1130
|
}
|
|
1131
|
+
const pending = value == null || value === false ? null : value === true ? "" : String(value);
|
|
1132
|
+
const refusal = contextualAttributeRefusal(el, name, pending, options.reactive ? "reactive" : "runtime");
|
|
1133
|
+
if (refusal !== ContextualRefusal.None) {
|
|
1134
|
+
warnContextualRefusal(options.label ?? "setSafeAttribute", name, refusal);
|
|
1135
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
1136
|
+
else el.removeAttribute(name);
|
|
1137
|
+
return false;
|
|
1138
|
+
}
|
|
735
1139
|
if (value == null) {
|
|
736
1140
|
if (ns) el.removeAttributeNS(ns, localName);
|
|
737
1141
|
else el.removeAttribute(name);
|
|
@@ -775,13 +1179,32 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
775
1179
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
776
1180
|
return true;
|
|
777
1181
|
}
|
|
778
|
-
const safe =
|
|
1182
|
+
const safe = str === "" ? "" : resolveAttributeValue(name, str, { element: el });
|
|
1183
|
+
if (safe === null) {
|
|
1184
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
1185
|
+
else el.removeAttribute(name);
|
|
1186
|
+
return true;
|
|
1187
|
+
}
|
|
779
1188
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
780
1189
|
if (current === safe) return true;
|
|
781
1190
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
782
1191
|
else el.setAttribute(name, safe);
|
|
783
1192
|
return true;
|
|
784
1193
|
}
|
|
1194
|
+
function setTrustedAttribute(el, name, value) {
|
|
1195
|
+
if (isHtmlContentAttribute(name)) {
|
|
1196
|
+
if (DEV) devWarn(`html: refusing static attribute "${name}" \u2014 the browser parses it as a nested document.`);
|
|
1197
|
+
return false;
|
|
1198
|
+
}
|
|
1199
|
+
const refusal = contextualAttributeRefusal(el, name, value, "static");
|
|
1200
|
+
if (refusal !== ContextualRefusal.None) {
|
|
1201
|
+
warnContextualRefusal("html (static attribute)", name, refusal);
|
|
1202
|
+
return false;
|
|
1203
|
+
}
|
|
1204
|
+
el.setAttribute(name, value);
|
|
1205
|
+
if (el.localName === "link") settleAttributeProvenance(el, name, "static");
|
|
1206
|
+
return true;
|
|
1207
|
+
}
|
|
785
1208
|
|
|
786
1209
|
// src/reactivity/track-core.ts
|
|
787
1210
|
var POOL_MAX = 4096;
|
|
@@ -1274,7 +1697,7 @@ function forEachSubscriber(signal2, visit) {
|
|
|
1274
1697
|
}
|
|
1275
1698
|
|
|
1276
1699
|
// src/reactivity/track.ts
|
|
1277
|
-
var _runtimeVersion = true ? "4.
|
|
1700
|
+
var _runtimeVersion = true ? "4.8.0" : "dev";
|
|
1278
1701
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
1279
1702
|
function resolveReactiveApi() {
|
|
1280
1703
|
const g2 = globalThis;
|
|
@@ -1345,7 +1768,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
1345
1768
|
reportError(err, { phase: "binding", name: `bindAttribute("${attr}")`, node: el });
|
|
1346
1769
|
return;
|
|
1347
1770
|
}
|
|
1348
|
-
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")
|
|
1771
|
+
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")`, reactive: true });
|
|
1349
1772
|
}
|
|
1350
1773
|
return reactiveBinding2(commit, el);
|
|
1351
1774
|
}
|
|
@@ -1370,7 +1793,7 @@ function bindDynamic(el, nameGetter, valueGetter) {
|
|
|
1370
1793
|
el.removeAttribute(prevName);
|
|
1371
1794
|
prevName = null;
|
|
1372
1795
|
}
|
|
1373
|
-
if (!setSafeAttribute(el, name, value, { label: "bindDynamic" })) return;
|
|
1796
|
+
if (!setSafeAttribute(el, name, value, { label: "bindDynamic", reactive: true })) return;
|
|
1374
1797
|
prevName = name;
|
|
1375
1798
|
}
|
|
1376
1799
|
const teardown = reactiveBinding2(commit, el);
|
|
@@ -1551,11 +1974,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
1551
1974
|
}
|
|
1552
1975
|
|
|
1553
1976
|
// src/core/rendering/tagFactory.ts
|
|
1554
|
-
var
|
|
1555
|
-
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
1556
|
-
function isBlockedTag(tag) {
|
|
1557
|
-
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
1558
|
-
}
|
|
1977
|
+
var SVG_NS3 = "http://www.w3.org/2000/svg";
|
|
1559
1978
|
var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
1560
1979
|
"config",
|
|
1561
1980
|
"location",
|
|
@@ -1582,8 +2001,35 @@ function toKebab(prop) {
|
|
|
1582
2001
|
}
|
|
1583
2002
|
function applyStyle(el, style2) {
|
|
1584
2003
|
if (typeof style2 === "function") {
|
|
2004
|
+
const getter = style2;
|
|
2005
|
+
let written = [];
|
|
2006
|
+
let wroteString = false;
|
|
1585
2007
|
const teardown = reactiveBinding2(() => {
|
|
1586
|
-
|
|
2008
|
+
const value = getter();
|
|
2009
|
+
if (value === null || typeof value !== "object") {
|
|
2010
|
+
written = [];
|
|
2011
|
+
wroteString = true;
|
|
2012
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(value), { element: el }));
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
const decl = el.style;
|
|
2016
|
+
if (wroteString) {
|
|
2017
|
+
el.removeAttribute("style");
|
|
2018
|
+
wroteString = false;
|
|
2019
|
+
}
|
|
2020
|
+
const next = [];
|
|
2021
|
+
for (const prop in value) {
|
|
2022
|
+
if (!Object.hasOwn(value, prop)) continue;
|
|
2023
|
+
const val = value[prop];
|
|
2024
|
+
if (val == null) continue;
|
|
2025
|
+
const name = toKebab(prop);
|
|
2026
|
+
next.push(name);
|
|
2027
|
+
decl.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
2028
|
+
}
|
|
2029
|
+
for (let i2 = 0; i2 < written.length; i2++) {
|
|
2030
|
+
if (next.indexOf(written[i2]) === -1) decl.removeProperty(written[i2]);
|
|
2031
|
+
}
|
|
2032
|
+
written = next;
|
|
1587
2033
|
}, el);
|
|
1588
2034
|
registerDisposer(el, teardown);
|
|
1589
2035
|
return;
|
|
@@ -1594,16 +2040,17 @@ function applyStyle(el, style2) {
|
|
|
1594
2040
|
}
|
|
1595
2041
|
const htmlEl = el;
|
|
1596
2042
|
for (const prop in style2) {
|
|
2043
|
+
if (!Object.hasOwn(style2, prop)) continue;
|
|
1597
2044
|
const val = style2[prop];
|
|
1598
2045
|
const name = toKebab(prop);
|
|
1599
2046
|
if (typeof val === "function") {
|
|
1600
2047
|
const getter = val;
|
|
1601
2048
|
const teardown = reactiveBinding2(() => {
|
|
1602
|
-
htmlEl.style.setProperty(name,
|
|
2049
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(getter()), { element: el }));
|
|
1603
2050
|
}, el);
|
|
1604
2051
|
registerDisposer(el, teardown);
|
|
1605
2052
|
} else {
|
|
1606
|
-
htmlEl.style.setProperty(name,
|
|
2053
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
1607
2054
|
}
|
|
1608
2055
|
}
|
|
1609
2056
|
}
|
|
@@ -1614,7 +2061,9 @@ function applyClass(el, cls) {
|
|
|
1614
2061
|
}
|
|
1615
2062
|
if (typeof cls === "function") {
|
|
1616
2063
|
const teardown = reactiveBinding2(() => {
|
|
1617
|
-
|
|
2064
|
+
const value = cls();
|
|
2065
|
+
if (value == null || value === false) el.removeAttribute("class");
|
|
2066
|
+
else el.setAttribute("class", value);
|
|
1618
2067
|
}, el);
|
|
1619
2068
|
registerDisposer(el, teardown);
|
|
1620
2069
|
return;
|
|
@@ -1623,6 +2072,7 @@ function applyClass(el, cls) {
|
|
|
1623
2072
|
let hasReactive = false;
|
|
1624
2073
|
let result = "";
|
|
1625
2074
|
for (const name in obj) {
|
|
2075
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
1626
2076
|
const val = obj[name];
|
|
1627
2077
|
if (typeof val === "function") {
|
|
1628
2078
|
hasReactive = true;
|
|
@@ -1634,6 +2084,7 @@ function applyClass(el, cls) {
|
|
|
1634
2084
|
const update = () => {
|
|
1635
2085
|
let r = "";
|
|
1636
2086
|
for (const name in obj) {
|
|
2087
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
1637
2088
|
const val = obj[name];
|
|
1638
2089
|
const active = typeof val === "function" ? val() : val;
|
|
1639
2090
|
if (active) r = r ? `${r} ${name}` : name;
|
|
@@ -1696,8 +2147,8 @@ function appendChildren(el, nodes) {
|
|
|
1696
2147
|
}
|
|
1697
2148
|
}
|
|
1698
2149
|
}
|
|
1699
|
-
|
|
1700
|
-
const blocked =
|
|
2150
|
+
function tagFactory(tag, ns) {
|
|
2151
|
+
const blocked = isBlockedElement(tag);
|
|
1701
2152
|
return (first, second) => {
|
|
1702
2153
|
if (blocked) {
|
|
1703
2154
|
throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
@@ -1745,7 +2196,9 @@ var tagFactory = (tag, ns) => {
|
|
|
1745
2196
|
const pClass = props.class;
|
|
1746
2197
|
if (pClass != null) applyClass(el, pClass);
|
|
1747
2198
|
const pId = props.id;
|
|
1748
|
-
if (pId
|
|
2199
|
+
if (typeof pId === "function") {
|
|
2200
|
+
registerDisposer(el, bindAttribute(el, "id", pId));
|
|
2201
|
+
} else if (pId != null) {
|
|
1749
2202
|
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
1750
2203
|
devWarn(
|
|
1751
2204
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
@@ -1758,6 +2211,7 @@ var tagFactory = (tag, ns) => {
|
|
|
1758
2211
|
const pOn = props.on;
|
|
1759
2212
|
if (pOn) {
|
|
1760
2213
|
for (const ev in pOn) {
|
|
2214
|
+
if (!Object.hasOwn(pOn, ev)) continue;
|
|
1761
2215
|
const handler = pOn[ev];
|
|
1762
2216
|
if (typeof handler === "function") {
|
|
1763
2217
|
el.addEventListener(ev, handler);
|
|
@@ -1784,6 +2238,7 @@ var tagFactory = (tag, ns) => {
|
|
|
1784
2238
|
continue;
|
|
1785
2239
|
// already handled above / below
|
|
1786
2240
|
default: {
|
|
2241
|
+
if (!Object.hasOwn(props, key)) continue;
|
|
1787
2242
|
const value = props[key];
|
|
1788
2243
|
if (value == null) continue;
|
|
1789
2244
|
if (isEventHandlerAttr(key)) continue;
|
|
@@ -1795,12 +2250,10 @@ var tagFactory = (tag, ns) => {
|
|
|
1795
2250
|
}
|
|
1796
2251
|
}
|
|
1797
2252
|
}
|
|
1798
|
-
if (
|
|
1799
|
-
props.onElement(el);
|
|
1800
|
-
}
|
|
2253
|
+
if (typeof props.onElement === "function") props.onElement(el);
|
|
1801
2254
|
return el;
|
|
1802
2255
|
};
|
|
1803
|
-
}
|
|
2256
|
+
}
|
|
1804
2257
|
|
|
1805
2258
|
// src/core/rendering/html.ts
|
|
1806
2259
|
var html = tagFactory("html");
|
|
@@ -1875,7 +2328,7 @@ var param = tagFactory("param");
|
|
|
1875
2328
|
var picture = tagFactory("picture");
|
|
1876
2329
|
var portal = tagFactory("portal");
|
|
1877
2330
|
var source = tagFactory("source");
|
|
1878
|
-
var svg = tagFactory("svg",
|
|
2331
|
+
var svg = tagFactory("svg", SVG_NS3);
|
|
1879
2332
|
var math = tagFactory("math");
|
|
1880
2333
|
var canvas = tagFactory("canvas");
|
|
1881
2334
|
var noscript = tagFactory("noscript");
|
|
@@ -1916,26 +2369,26 @@ var base = tagFactory("base");
|
|
|
1916
2369
|
var link = tagFactory("link");
|
|
1917
2370
|
var meta = tagFactory("meta");
|
|
1918
2371
|
var style = tagFactory("style");
|
|
1919
|
-
var circle = tagFactory("circle",
|
|
1920
|
-
var ellipse = tagFactory("ellipse",
|
|
1921
|
-
var g = tagFactory("g",
|
|
1922
|
-
var line = tagFactory("line",
|
|
1923
|
-
var path = tagFactory("path",
|
|
1924
|
-
var polygon = tagFactory("polygon",
|
|
1925
|
-
var polyline = tagFactory("polyline",
|
|
1926
|
-
var rect = tagFactory("rect",
|
|
1927
|
-
var text = tagFactory("text",
|
|
1928
|
-
var tspan = tagFactory("tspan",
|
|
1929
|
-
var defs = tagFactory("defs",
|
|
1930
|
-
var clipPath = tagFactory("clipPath",
|
|
1931
|
-
var mask = tagFactory("mask",
|
|
1932
|
-
var pattern = tagFactory("pattern",
|
|
1933
|
-
var linearGradient = tagFactory("linearGradient",
|
|
1934
|
-
var radialGradient = tagFactory("radialGradient",
|
|
1935
|
-
var stop = tagFactory("stop",
|
|
1936
|
-
var use = tagFactory("use",
|
|
1937
|
-
var symbol = tagFactory("symbol",
|
|
1938
|
-
var marker = tagFactory("marker",
|
|
2372
|
+
var circle = tagFactory("circle", SVG_NS3);
|
|
2373
|
+
var ellipse = tagFactory("ellipse", SVG_NS3);
|
|
2374
|
+
var g = tagFactory("g", SVG_NS3);
|
|
2375
|
+
var line = tagFactory("line", SVG_NS3);
|
|
2376
|
+
var path = tagFactory("path", SVG_NS3);
|
|
2377
|
+
var polygon = tagFactory("polygon", SVG_NS3);
|
|
2378
|
+
var polyline = tagFactory("polyline", SVG_NS3);
|
|
2379
|
+
var rect = tagFactory("rect", SVG_NS3);
|
|
2380
|
+
var text = tagFactory("text", SVG_NS3);
|
|
2381
|
+
var tspan = tagFactory("tspan", SVG_NS3);
|
|
2382
|
+
var defs = tagFactory("defs", SVG_NS3);
|
|
2383
|
+
var clipPath = tagFactory("clipPath", SVG_NS3);
|
|
2384
|
+
var mask = tagFactory("mask", SVG_NS3);
|
|
2385
|
+
var pattern = tagFactory("pattern", SVG_NS3);
|
|
2386
|
+
var linearGradient = tagFactory("linearGradient", SVG_NS3);
|
|
2387
|
+
var radialGradient = tagFactory("radialGradient", SVG_NS3);
|
|
2388
|
+
var stop = tagFactory("stop", SVG_NS3);
|
|
2389
|
+
var use = tagFactory("use", SVG_NS3);
|
|
2390
|
+
var symbol = tagFactory("symbol", SVG_NS3);
|
|
2391
|
+
var marker = tagFactory("marker", SVG_NS3);
|
|
1939
2392
|
var center = tagFactory("center");
|
|
1940
2393
|
var font = tagFactory("font");
|
|
1941
2394
|
var marquee = tagFactory("marquee");
|
|
@@ -2049,10 +2502,13 @@ function safeCall(cb, hookName) {
|
|
|
2049
2502
|
return void 0;
|
|
2050
2503
|
}
|
|
2051
2504
|
}
|
|
2052
|
-
function runMountCallback(callback, hookName, element) {
|
|
2505
|
+
function runMountCallback(callback, hookName, element, isDisposed) {
|
|
2053
2506
|
const cleanup3 = safeCall(callback, hookName);
|
|
2054
|
-
if (typeof cleanup3
|
|
2055
|
-
|
|
2507
|
+
if (typeof cleanup3 !== "function") return;
|
|
2508
|
+
if (isDisposed() || !element.isConnected) {
|
|
2509
|
+
safeCall(cleanup3, "onUnmount");
|
|
2510
|
+
} else {
|
|
2511
|
+
onUnmount(cleanup3, element);
|
|
2056
2512
|
}
|
|
2057
2513
|
}
|
|
2058
2514
|
var mountWatchers = /* @__PURE__ */ new WeakMap();
|
|
@@ -2214,25 +2670,26 @@ function onMount(callback, element) {
|
|
|
2214
2670
|
if (typeof document === "undefined") return;
|
|
2215
2671
|
if (element) {
|
|
2216
2672
|
let disposed = false;
|
|
2673
|
+
const isDisposed = () => disposed;
|
|
2217
2674
|
registerDisposer(element, () => {
|
|
2218
2675
|
disposed = true;
|
|
2219
2676
|
});
|
|
2220
2677
|
if (element.isConnected) {
|
|
2221
2678
|
queueMicrotask(() => {
|
|
2222
2679
|
if (disposed) return;
|
|
2223
|
-
runMountCallback(callback, "onMount", element);
|
|
2680
|
+
runMountCallback(callback, "onMount", element, isDisposed);
|
|
2224
2681
|
});
|
|
2225
2682
|
return;
|
|
2226
2683
|
}
|
|
2227
2684
|
queueMicrotask(() => {
|
|
2228
2685
|
if (disposed) return;
|
|
2229
2686
|
if (element.isConnected) {
|
|
2230
|
-
runMountCallback(callback, "onMount", element);
|
|
2687
|
+
runMountCallback(callback, "onMount", element, isDisposed);
|
|
2231
2688
|
return;
|
|
2232
2689
|
}
|
|
2233
2690
|
const unregister = registerMountWatcher(element, () => {
|
|
2234
2691
|
if (disposed) return;
|
|
2235
|
-
runMountCallback(callback, "onMount", element);
|
|
2692
|
+
runMountCallback(callback, "onMount", element, isDisposed);
|
|
2236
2693
|
});
|
|
2237
2694
|
registerDisposer(element, unregister);
|
|
2238
2695
|
});
|
|
@@ -2269,6 +2726,14 @@ function onCleanup(callback, element) {
|
|
|
2269
2726
|
registerDisposer(element, callback);
|
|
2270
2727
|
}
|
|
2271
2728
|
|
|
2729
|
+
// src/core/devtoolsHook.ts
|
|
2730
|
+
function emitDevtools(hook, event, payload) {
|
|
2731
|
+
try {
|
|
2732
|
+
hook.emit(event, payload);
|
|
2733
|
+
} catch {
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2272
2737
|
// src/core/ssr-context.ts
|
|
2273
2738
|
var SSR_KEY = /* @__PURE__ */ Symbol.for("sibujs.ssr.v1");
|
|
2274
2739
|
function detectSSRShared() {
|
|
@@ -2506,12 +2971,17 @@ function effect(effectFn, options) {
|
|
|
2506
2971
|
try {
|
|
2507
2972
|
retrack2(ctx.bodyFn, ctx.subscriber);
|
|
2508
2973
|
if (ctx.rerunPending) drainReruns(ctx);
|
|
2974
|
+
} catch (err) {
|
|
2975
|
+
ctx.disposed = true;
|
|
2976
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
2977
|
+
cleanup2(ctx.subscriber);
|
|
2978
|
+
throw err;
|
|
2509
2979
|
} finally {
|
|
2510
2980
|
ctx.running = false;
|
|
2511
2981
|
ctx.rerunPending = false;
|
|
2512
2982
|
}
|
|
2513
2983
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2514
|
-
if (hook) hook
|
|
2984
|
+
if (hook) emitDevtools(hook, "effect:create", { effectFn });
|
|
2515
2985
|
return () => disposeEffect(ctx);
|
|
2516
2986
|
}
|
|
2517
2987
|
|
|
@@ -2598,7 +3068,7 @@ function signal(initial, options) {
|
|
|
2598
3068
|
state2.__v++;
|
|
2599
3069
|
if (DEV) {
|
|
2600
3070
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2601
|
-
if (hook) hook
|
|
3071
|
+
if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
2602
3072
|
}
|
|
2603
3073
|
if (!enqueueBatchedSignal(state2)) {
|
|
2604
3074
|
notifySubscribers2(state2);
|
|
@@ -2612,7 +3082,7 @@ function signal(initial, options) {
|
|
|
2612
3082
|
state2.value = newValue;
|
|
2613
3083
|
state2.__v++;
|
|
2614
3084
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2615
|
-
if (hook) hook
|
|
3085
|
+
if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
2616
3086
|
if (!enqueueBatchedSignal(state2)) {
|
|
2617
3087
|
notifySubscribers2(state2);
|
|
2618
3088
|
}
|
|
@@ -2631,7 +3101,7 @@ function signal(initial, options) {
|
|
|
2631
3101
|
}
|
|
2632
3102
|
if (DEV) {
|
|
2633
3103
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2634
|
-
if (hook) hook
|
|
3104
|
+
if (hook) emitDevtools(hook, "signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
2635
3105
|
}
|
|
2636
3106
|
return [get, set];
|
|
2637
3107
|
}
|
|
@@ -3444,36 +3914,34 @@ function Loading(props = {}) {
|
|
|
3444
3914
|
const { text: text2, variant = "spinner", size = "md" } = props;
|
|
3445
3915
|
const sizeClass = size !== "md" ? ` sibu-loading-${size}` : "";
|
|
3446
3916
|
if (variant === "dots") {
|
|
3447
|
-
return div(
|
|
3917
|
+
return div(
|
|
3918
|
+
{
|
|
3919
|
+
class: `sibu-loading${sizeClass}`,
|
|
3920
|
+
role: "status",
|
|
3921
|
+
"aria-live": "polite",
|
|
3922
|
+
// When there's no visible text, give the live region an accessible name
|
|
3923
|
+
// so it isn't announced as an empty status.
|
|
3924
|
+
"aria-label": text2 ? void 0 : "Loading"
|
|
3925
|
+
},
|
|
3926
|
+
[
|
|
3927
|
+
div({ class: "sibu-loading-dots" }, [
|
|
3928
|
+
span({ class: "sibu-loading-dot" }),
|
|
3929
|
+
span({ class: "sibu-loading-dot" }),
|
|
3930
|
+
span({ class: "sibu-loading-dot" })
|
|
3931
|
+
]),
|
|
3932
|
+
text2 ? span({ class: "sibu-loading-text" }, text2) : null
|
|
3933
|
+
]
|
|
3934
|
+
);
|
|
3935
|
+
}
|
|
3936
|
+
return div(
|
|
3937
|
+
{
|
|
3448
3938
|
class: `sibu-loading${sizeClass}`,
|
|
3449
3939
|
role: "status",
|
|
3450
3940
|
"aria-live": "polite",
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
div({
|
|
3456
|
-
class: "sibu-loading-dots",
|
|
3457
|
-
nodes: [
|
|
3458
|
-
span({ class: "sibu-loading-dot" }),
|
|
3459
|
-
span({ class: "sibu-loading-dot" }),
|
|
3460
|
-
span({ class: "sibu-loading-dot" })
|
|
3461
|
-
]
|
|
3462
|
-
}),
|
|
3463
|
-
text2 ? span({ class: "sibu-loading-text", nodes: text2 }) : null
|
|
3464
|
-
].filter(Boolean)
|
|
3465
|
-
});
|
|
3466
|
-
}
|
|
3467
|
-
return div({
|
|
3468
|
-
class: `sibu-loading${sizeClass}`,
|
|
3469
|
-
role: "status",
|
|
3470
|
-
"aria-live": "polite",
|
|
3471
|
-
"aria-label": text2 ? void 0 : "Loading",
|
|
3472
|
-
nodes: [
|
|
3473
|
-
div({ class: "sibu-loading-spinner" }),
|
|
3474
|
-
text2 ? span({ class: "sibu-loading-text", nodes: text2 }) : null
|
|
3475
|
-
].filter(Boolean)
|
|
3476
|
-
});
|
|
3941
|
+
"aria-label": text2 ? void 0 : "Loading"
|
|
3942
|
+
},
|
|
3943
|
+
[div({ class: "sibu-loading-spinner" }), text2 ? span({ class: "sibu-loading-text" }, text2) : null]
|
|
3944
|
+
);
|
|
3477
3945
|
}
|
|
3478
3946
|
|
|
3479
3947
|
// src/core/rendering/action.ts
|
|
@@ -3579,13 +4047,35 @@ registerAction("copyOnClick", copyOnClick);
|
|
|
3579
4047
|
registerAction("autoResize", autoResize);
|
|
3580
4048
|
registerAction("trapFocus", trapFocus);
|
|
3581
4049
|
|
|
4050
|
+
// src/utils/adoptThenable.ts
|
|
4051
|
+
function adoptThenable(value) {
|
|
4052
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return null;
|
|
4053
|
+
let then;
|
|
4054
|
+
try {
|
|
4055
|
+
then = value.then;
|
|
4056
|
+
} catch (error) {
|
|
4057
|
+
return Promise.reject(error);
|
|
4058
|
+
}
|
|
4059
|
+
if (typeof then !== "function") return null;
|
|
4060
|
+
return new Promise((resolve, reject) => {
|
|
4061
|
+
queueMicrotask(() => {
|
|
4062
|
+
try {
|
|
4063
|
+
Reflect.apply(then, value, [resolve, reject]);
|
|
4064
|
+
} catch (error) {
|
|
4065
|
+
reject(error);
|
|
4066
|
+
}
|
|
4067
|
+
});
|
|
4068
|
+
});
|
|
4069
|
+
}
|
|
4070
|
+
|
|
3582
4071
|
// src/core/rendering/catch.ts
|
|
3583
4072
|
var globalErrorHandler = null;
|
|
3584
4073
|
function catchError(fn, onError) {
|
|
3585
4074
|
try {
|
|
3586
4075
|
const result = fn();
|
|
3587
|
-
|
|
3588
|
-
|
|
4076
|
+
const adopted = adoptThenable(result);
|
|
4077
|
+
if (adopted) {
|
|
4078
|
+
adopted.then(void 0, (err) => {
|
|
3589
4079
|
if (onError) {
|
|
3590
4080
|
onError(err, "async");
|
|
3591
4081
|
} else if (globalErrorHandler) {
|
|
@@ -3712,6 +4202,10 @@ function attachBranch(parent, anchor, branch, attachedOnce, where) {
|
|
|
3712
4202
|
parent.insertBefore(node, anchor.nextSibling);
|
|
3713
4203
|
return { node, owned };
|
|
3714
4204
|
}
|
|
4205
|
+
function releaseBranchNode(node, owned) {
|
|
4206
|
+
if (owned) dispose(node);
|
|
4207
|
+
node.parentNode?.removeChild(node);
|
|
4208
|
+
}
|
|
3715
4209
|
function when(condition, thenBranch, elseBranch) {
|
|
3716
4210
|
const anchor = document.createComment("when");
|
|
3717
4211
|
let currentNode = null;
|
|
@@ -3725,16 +4219,15 @@ function when(condition, thenBranch, elseBranch) {
|
|
|
3725
4219
|
const show2 = condition();
|
|
3726
4220
|
const parent = anchor.parentNode;
|
|
3727
4221
|
if (!parent) return;
|
|
3728
|
-
if (initialized && show2
|
|
4222
|
+
if (initialized && Object.is(show2, lastCondition)) return;
|
|
3729
4223
|
lastCondition = show2;
|
|
3730
4224
|
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
3731
4225
|
if (currentNode?.parentNode) {
|
|
3732
|
-
|
|
3733
|
-
currentNode.parentNode.removeChild(currentNode);
|
|
4226
|
+
releaseBranchNode(currentNode, currentNodeOwned);
|
|
3734
4227
|
currentNode = null;
|
|
3735
4228
|
}
|
|
3736
4229
|
const branch = show2 ? thenBranch : elseBranch !== void 0 ? elseBranch : null;
|
|
3737
|
-
const attached = attachBranch(parent, anchor, branch, attachedOnce, "when");
|
|
4230
|
+
const attached = untracked2(() => attachBranch(parent, anchor, branch, attachedOnce, "when"));
|
|
3738
4231
|
currentNode = attached.node;
|
|
3739
4232
|
currentNodeOwned = attached.owned;
|
|
3740
4233
|
restoreFocusWithin(focused, currentNode ? [currentNode] : [], "when");
|
|
@@ -3744,6 +4237,8 @@ function when(condition, thenBranch, elseBranch) {
|
|
|
3744
4237
|
registerDisposer(anchor, () => {
|
|
3745
4238
|
disposed = true;
|
|
3746
4239
|
stopBinding();
|
|
4240
|
+
if (currentNode) releaseBranchNode(currentNode, currentNodeOwned);
|
|
4241
|
+
currentNode = null;
|
|
3747
4242
|
});
|
|
3748
4243
|
if (!initialized) {
|
|
3749
4244
|
queueMicrotask(() => {
|
|
@@ -3769,12 +4264,11 @@ function match(value, cases, fallback) {
|
|
|
3769
4264
|
lastKey = key;
|
|
3770
4265
|
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
3771
4266
|
if (currentNode?.parentNode) {
|
|
3772
|
-
|
|
3773
|
-
currentNode.parentNode.removeChild(currentNode);
|
|
4267
|
+
releaseBranchNode(currentNode, currentNodeOwned);
|
|
3774
4268
|
currentNode = null;
|
|
3775
4269
|
}
|
|
3776
4270
|
const branch = Object.hasOwn(cases, key) ? cases[key] : fallback;
|
|
3777
|
-
const attached = attachBranch(parent, anchor, branch ?? null, attachedOnce, "match");
|
|
4271
|
+
const attached = untracked2(() => attachBranch(parent, anchor, branch ?? null, attachedOnce, "match"));
|
|
3778
4272
|
currentNode = attached.node;
|
|
3779
4273
|
currentNodeOwned = attached.owned;
|
|
3780
4274
|
restoreFocusWithin(focused, currentNode ? [currentNode] : [], "match");
|
|
@@ -3784,6 +4278,8 @@ function match(value, cases, fallback) {
|
|
|
3784
4278
|
registerDisposer(anchor, () => {
|
|
3785
4279
|
disposed = true;
|
|
3786
4280
|
stopBinding();
|
|
4281
|
+
if (currentNode) releaseBranchNode(currentNode, currentNodeOwned);
|
|
4282
|
+
currentNode = null;
|
|
3787
4283
|
});
|
|
3788
4284
|
if (!initialized) {
|
|
3789
4285
|
queueMicrotask(() => {
|
|
@@ -3804,11 +4300,17 @@ var componentRegistry = globalSingleton(
|
|
|
3804
4300
|
/* @__PURE__ */ Symbol.for("sibujs.components.registry.v1"),
|
|
3805
4301
|
() => /* @__PURE__ */ new Map()
|
|
3806
4302
|
);
|
|
4303
|
+
var registryVersion = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.components.registryVersion.v1"), () => signal(0));
|
|
4304
|
+
function bumpRegistry() {
|
|
4305
|
+
const [read, write] = registryVersion;
|
|
4306
|
+
write(untracked2(read) + 1);
|
|
4307
|
+
}
|
|
3807
4308
|
function registerComponent(name, component) {
|
|
3808
4309
|
componentRegistry.set(name, component);
|
|
4310
|
+
bumpRegistry();
|
|
3809
4311
|
}
|
|
3810
4312
|
function unregisterComponent(name) {
|
|
3811
|
-
componentRegistry.delete(name);
|
|
4313
|
+
if (componentRegistry.delete(name)) bumpRegistry();
|
|
3812
4314
|
}
|
|
3813
4315
|
function resolveComponent(name) {
|
|
3814
4316
|
const component = componentRegistry.get(name);
|
|
@@ -3819,14 +4321,21 @@ function resolveComponent(name) {
|
|
|
3819
4321
|
}
|
|
3820
4322
|
function DynamicComponent(is) {
|
|
3821
4323
|
const container = div({ class: "sibu-dynamic" });
|
|
4324
|
+
const NONE = {};
|
|
4325
|
+
let shown = NONE;
|
|
3822
4326
|
function render() {
|
|
3823
4327
|
const target = is();
|
|
3824
|
-
let
|
|
4328
|
+
let component;
|
|
3825
4329
|
if (typeof target === "function") {
|
|
3826
|
-
|
|
4330
|
+
component = target;
|
|
3827
4331
|
} else {
|
|
3828
|
-
|
|
4332
|
+
registryVersion[0]();
|
|
4333
|
+
component = componentRegistry.get(target);
|
|
3829
4334
|
}
|
|
4335
|
+
const next = component ?? `missing:${target}`;
|
|
4336
|
+
if (next === shown) return;
|
|
4337
|
+
const el = untracked2(() => component ? component() : div(`[Component "${target}" not found]`));
|
|
4338
|
+
shown = next;
|
|
3830
4339
|
replaceChildrenSafely(container, el);
|
|
3831
4340
|
}
|
|
3832
4341
|
const untrack = track2(render);
|
|
@@ -4090,31 +4599,29 @@ function Fragment(nodes) {
|
|
|
4090
4599
|
if (Array.isArray(child)) {
|
|
4091
4600
|
for (const nested of child) {
|
|
4092
4601
|
if (nested == null || typeof nested === "boolean") continue;
|
|
4093
|
-
|
|
4602
|
+
appendChild(frag, nested);
|
|
4094
4603
|
}
|
|
4095
4604
|
} else {
|
|
4096
|
-
|
|
4605
|
+
appendChild(frag, child);
|
|
4097
4606
|
}
|
|
4098
4607
|
}
|
|
4099
4608
|
return frag;
|
|
4100
4609
|
}
|
|
4101
|
-
function
|
|
4102
|
-
if (child == null) {
|
|
4103
|
-
return document.createTextNode("");
|
|
4104
|
-
}
|
|
4610
|
+
function appendChild(frag, child) {
|
|
4105
4611
|
if (child instanceof Node) {
|
|
4106
|
-
|
|
4612
|
+
frag.appendChild(child);
|
|
4613
|
+
return;
|
|
4107
4614
|
}
|
|
4108
4615
|
if (typeof child === "function") {
|
|
4109
|
-
const
|
|
4110
|
-
|
|
4111
|
-
|
|
4616
|
+
const placeholder = document.createComment("");
|
|
4617
|
+
frag.appendChild(placeholder);
|
|
4618
|
+
registerDisposer(placeholder, bindChildNode(placeholder, child));
|
|
4619
|
+
return;
|
|
4112
4620
|
}
|
|
4113
|
-
|
|
4621
|
+
frag.appendChild(document.createTextNode(String(child)));
|
|
4114
4622
|
}
|
|
4115
4623
|
|
|
4116
4624
|
// src/core/rendering/htm.ts
|
|
4117
|
-
var RAW_TEXT_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
4118
4625
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
4119
4626
|
"area",
|
|
4120
4627
|
"base",
|
|
@@ -4337,7 +4844,7 @@ function parseTemplate(strings) {
|
|
|
4337
4844
|
children.push({ t: 0, el: { tag, svg: SVG_TAGS.has(tag), attrs, children: [] } });
|
|
4338
4845
|
} else {
|
|
4339
4846
|
const inner = parseChildren();
|
|
4340
|
-
if (
|
|
4847
|
+
if (isCodeTextElement(tag)) {
|
|
4341
4848
|
for (let i2 = 0; i2 < inner.length; i2++) {
|
|
4342
4849
|
if (inner[i2].t === 2) {
|
|
4343
4850
|
throw new Error(
|
|
@@ -4363,12 +4870,12 @@ function parseTemplate(strings) {
|
|
|
4363
4870
|
return parseChildren();
|
|
4364
4871
|
}
|
|
4365
4872
|
function executeElement(tmpl, values) {
|
|
4366
|
-
const el = tmpl.svg ? document.createElementNS(
|
|
4873
|
+
const el = tmpl.svg ? document.createElementNS(SVG_NS3, tmpl.tag) : document.createElement(tmpl.tag);
|
|
4367
4874
|
for (let i2 = 0; i2 < tmpl.attrs.length; i2++) {
|
|
4368
4875
|
const attr = tmpl.attrs[i2];
|
|
4369
4876
|
switch (attr.t) {
|
|
4370
4877
|
case 0:
|
|
4371
|
-
el
|
|
4878
|
+
setTrustedAttribute(el, attr.name, attr.value);
|
|
4372
4879
|
break;
|
|
4373
4880
|
case 1: {
|
|
4374
4881
|
const name = attr.name;
|
|
@@ -4401,7 +4908,7 @@ function executeElement(tmpl, values) {
|
|
|
4401
4908
|
break;
|
|
4402
4909
|
}
|
|
4403
4910
|
case 4:
|
|
4404
|
-
el
|
|
4911
|
+
setTrustedAttribute(el, attr.name, "");
|
|
4405
4912
|
break;
|
|
4406
4913
|
}
|
|
4407
4914
|
}
|
|
@@ -4446,6 +4953,12 @@ function html2(strings, ...values) {
|
|
|
4446
4953
|
tmpl = parseTemplate(strings);
|
|
4447
4954
|
cache.set(strings, tmpl);
|
|
4448
4955
|
}
|
|
4956
|
+
return renderTemplate(tmpl, values);
|
|
4957
|
+
}
|
|
4958
|
+
function __renderParsedTemplate(tree, values) {
|
|
4959
|
+
return renderTemplate(tree, values);
|
|
4960
|
+
}
|
|
4961
|
+
function renderTemplate(tmpl, values) {
|
|
4449
4962
|
if (tmpl.length === 1 && tmpl[0].t === 0) {
|
|
4450
4963
|
return executeElement(tmpl[0].el, values);
|
|
4451
4964
|
}
|
|
@@ -4580,25 +5093,77 @@ function mount(component, container) {
|
|
|
4580
5093
|
typeof component === "function" || component instanceof Node,
|
|
4581
5094
|
"mount: first argument must be a component function or a DOM Node."
|
|
4582
5095
|
);
|
|
4583
|
-
const
|
|
4584
|
-
const
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
5096
|
+
const now = () => typeof performance !== "undefined" ? performance.now() : 0;
|
|
5097
|
+
const startTime = now();
|
|
5098
|
+
let range = null;
|
|
5099
|
+
const attach = (built) => {
|
|
5100
|
+
if (built instanceof DocumentFragment) {
|
|
5101
|
+
const start = document.createComment("");
|
|
5102
|
+
const end = document.createComment("");
|
|
5103
|
+
built.insertBefore(start, built.firstChild);
|
|
5104
|
+
built.appendChild(end);
|
|
5105
|
+
range = { start, end };
|
|
5106
|
+
}
|
|
5107
|
+
container.appendChild(built);
|
|
5108
|
+
};
|
|
5109
|
+
let node;
|
|
5110
|
+
if (typeof component === "function") {
|
|
5111
|
+
node = withDisposerRollback(() => {
|
|
5112
|
+
const built = component();
|
|
5113
|
+
attach(built);
|
|
5114
|
+
return built;
|
|
5115
|
+
});
|
|
5116
|
+
} else {
|
|
5117
|
+
node = component;
|
|
5118
|
+
attach(node);
|
|
4590
5119
|
}
|
|
5120
|
+
const duration = now() - startTime;
|
|
5121
|
+
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
5122
|
+
if (hook) emitDevtools(hook, "app:init", { rootElement: node, container, duration });
|
|
5123
|
+
const mounted = range;
|
|
4591
5124
|
return {
|
|
4592
5125
|
node,
|
|
4593
5126
|
unmount() {
|
|
4594
|
-
if (hook) hook
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
5127
|
+
if (hook) emitDevtools(hook, "app:unmount", { rootElement: node });
|
|
5128
|
+
if (mounted) {
|
|
5129
|
+
unmountRange(mounted.start, mounted.end);
|
|
5130
|
+
return;
|
|
4598
5131
|
}
|
|
5132
|
+
dispose(node);
|
|
5133
|
+
node.parentNode?.removeChild(node);
|
|
4599
5134
|
}
|
|
4600
5135
|
};
|
|
4601
5136
|
}
|
|
5137
|
+
function unmountRange(start, end) {
|
|
5138
|
+
const parent = start.parentNode;
|
|
5139
|
+
if (!parent && !end.parentNode) return;
|
|
5140
|
+
let budget = MAX_DRAIN_TEARDOWNS;
|
|
5141
|
+
for (let n = start.nextSibling; n && n !== end; n = n.nextSibling) budget++;
|
|
5142
|
+
let before = start;
|
|
5143
|
+
let after = null;
|
|
5144
|
+
let intact = true;
|
|
5145
|
+
for (; ; ) {
|
|
5146
|
+
if (start.parentNode !== parent || end.parentNode !== parent) intact = false;
|
|
5147
|
+
else if (start.previousSibling !== before || end.nextSibling !== after) {
|
|
5148
|
+
before = start.previousSibling;
|
|
5149
|
+
after = end.nextSibling;
|
|
5150
|
+
intact = !!(start.compareDocumentPosition(end) & 4);
|
|
5151
|
+
}
|
|
5152
|
+
const n = start.nextSibling;
|
|
5153
|
+
if (!intact || n === end) break;
|
|
5154
|
+
if (budget-- <= 0) {
|
|
5155
|
+
reportDrainRunaway("mount", MAX_DRAIN_TEARDOWNS, 1);
|
|
5156
|
+
return;
|
|
5157
|
+
}
|
|
5158
|
+
dispose(n);
|
|
5159
|
+
if (n.parentNode === parent) parent.removeChild(n);
|
|
5160
|
+
}
|
|
5161
|
+
if (!intact) {
|
|
5162
|
+
reportError(new Error("[SibuJS mount] fragment markers lost"), { phase: "cleanup", name: "mount" });
|
|
5163
|
+
}
|
|
5164
|
+
start.parentNode?.removeChild(start);
|
|
5165
|
+
end.parentNode?.removeChild(end);
|
|
5166
|
+
}
|
|
4602
5167
|
|
|
4603
5168
|
// src/core/rendering/portal.ts
|
|
4604
5169
|
function Portal(nodes, target) {
|
|
@@ -5034,17 +5599,17 @@ function derived(getter, options) {
|
|
|
5034
5599
|
cs._d = false;
|
|
5035
5600
|
cs._init = true;
|
|
5036
5601
|
};
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
try {
|
|
5602
|
+
try {
|
|
5603
|
+
track2(() => {
|
|
5040
5604
|
cs._v = getter();
|
|
5041
5605
|
cs._d = false;
|
|
5042
5606
|
cs._init = true;
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5607
|
+
}, markDirty);
|
|
5608
|
+
} catch (err) {
|
|
5609
|
+
disposed = true;
|
|
5610
|
+
cleanup2(markDirty);
|
|
5611
|
+
throw err;
|
|
5612
|
+
}
|
|
5048
5613
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
5049
5614
|
const validate = () => {
|
|
5050
5615
|
if (!cs._d || disposed || pendingError !== void 0) return;
|
|
@@ -5063,7 +5628,7 @@ function derived(getter, options) {
|
|
|
5063
5628
|
if (disposed) cleanup2(markDirty);
|
|
5064
5629
|
}
|
|
5065
5630
|
if (hook && !disposed && !Object.is(oldValue, cs._v)) {
|
|
5066
|
-
hook
|
|
5631
|
+
emitDevtools(hook, "computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
5067
5632
|
}
|
|
5068
5633
|
};
|
|
5069
5634
|
cs._validate = validate;
|
|
@@ -5114,7 +5679,7 @@ function derived(getter, options) {
|
|
|
5114
5679
|
}
|
|
5115
5680
|
}
|
|
5116
5681
|
};
|
|
5117
|
-
if (hook) hook
|
|
5682
|
+
if (hook) emitDevtools(hook, "computed:create", { signal: cs, name: debugName, getter: computedGetter });
|
|
5118
5683
|
return computedGetter;
|
|
5119
5684
|
}
|
|
5120
5685
|
|
|
@@ -5482,7 +6047,7 @@ function enhance(target, setup) {
|
|
|
5482
6047
|
bindNode(el, () => {
|
|
5483
6048
|
const v = value();
|
|
5484
6049
|
const next = v == null ? null : String(v);
|
|
5485
|
-
setSafeAttribute(el, name, next, { syncValueProperty: false, label: "enhance attr()" });
|
|
6050
|
+
setSafeAttribute(el, name, next, { syncValueProperty: false, label: "enhance attr()", reactive: true });
|
|
5486
6051
|
})
|
|
5487
6052
|
);
|
|
5488
6053
|
});
|
|
@@ -5754,27 +6319,6 @@ function trustHTML(html3) {
|
|
|
5754
6319
|
}
|
|
5755
6320
|
var DEFAULT_MAX_SSR_BYTES = 1024 * 1024;
|
|
5756
6321
|
|
|
5757
|
-
// src/utils/adoptThenable.ts
|
|
5758
|
-
function adoptThenable(value) {
|
|
5759
|
-
if (value === null || typeof value !== "object" && typeof value !== "function") return null;
|
|
5760
|
-
let then;
|
|
5761
|
-
try {
|
|
5762
|
-
then = value.then;
|
|
5763
|
-
} catch (error) {
|
|
5764
|
-
return Promise.reject(error);
|
|
5765
|
-
}
|
|
5766
|
-
if (typeof then !== "function") return null;
|
|
5767
|
-
return new Promise((resolve, reject) => {
|
|
5768
|
-
queueMicrotask(() => {
|
|
5769
|
-
try {
|
|
5770
|
-
Reflect.apply(then, value, [resolve, reject]);
|
|
5771
|
-
} catch (error) {
|
|
5772
|
-
reject(error);
|
|
5773
|
-
}
|
|
5774
|
-
});
|
|
5775
|
-
});
|
|
5776
|
-
}
|
|
5777
|
-
|
|
5778
6322
|
// src/reactivity/concurrent.ts
|
|
5779
6323
|
function defer(getter) {
|
|
5780
6324
|
const [value, setValue] = signal(getter());
|
|
@@ -5875,6 +6419,7 @@ function nextTick() {
|
|
|
5875
6419
|
Portal,
|
|
5876
6420
|
SVG_NS,
|
|
5877
6421
|
Suspense,
|
|
6422
|
+
__renderParsedTemplate,
|
|
5878
6423
|
__resetIdCounter,
|
|
5879
6424
|
a,
|
|
5880
6425
|
abbr,
|