sibujs 4.7.0 → 4.9.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 +48 -6
- package/dist/browser.d.cts +26 -2
- package/dist/browser.d.ts +26 -2
- package/dist/browser.js +6 -5
- package/dist/build.cjs +539 -96
- 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-Z3OHK6QT.js → chunk-2K3Z3XO4.js} +5 -5
- package/dist/chunk-3ACAAQIN.js +224 -0
- package/dist/{chunk-WOLJZUFQ.js → chunk-562UVHMM.js} +32 -15
- package/dist/{chunk-UOL2ECCS.js → chunk-5MLWTIQE.js} +18 -12
- package/dist/{chunk-H3SRKIYX.js → chunk-62BDYGAG.js} +8 -0
- package/dist/{chunk-3QWBSL5R.js → chunk-7OV5Q2UU.js} +8 -5
- package/dist/{chunk-SLM3IA34.js → chunk-CDBKFGXN.js} +1 -1
- package/dist/{chunk-4AWA2PVD.js → chunk-CF2KCWRE.js} +10 -5
- package/dist/{chunk-BSY63EM6.js → chunk-DRMLIF6M.js} +20 -5
- package/dist/{chunk-2INLLLMZ.js → chunk-EXXSN3BW.js} +202 -26
- package/dist/{chunk-HURREPU2.js → chunk-FC6KCJSA.js} +87 -150
- package/dist/{chunk-BC2SECJD.js → chunk-FHCZMHHE.js} +1 -1
- package/dist/{chunk-XYV3EDB7.js → chunk-FNOK662L.js} +63 -38
- package/dist/{chunk-JWKYU5GV.js → chunk-G2WHYEL7.js} +1 -1
- package/dist/{chunk-DKXRACVN.js → chunk-K6K5ACO6.js} +6 -6
- package/dist/{chunk-VZSG24LS.js → chunk-KG25XMGP.js} +45 -17
- package/dist/{chunk-FNJXNGYZ.js → chunk-MPWDSTYK.js} +58 -6
- package/dist/{chunk-UNWRJRKC.js → chunk-NQMKWBKU.js} +1 -1
- package/dist/{chunk-7LUJQAOJ.js → chunk-QBKCK6MJ.js} +1 -1
- package/dist/{chunk-WEQ3DMVL.js → chunk-SBTZEYNI.js} +1 -1
- package/dist/{chunk-FQRUXCEE.js → chunk-SYHGGDNW.js} +1 -1
- package/dist/{chunk-XZR4PXRE.js → chunk-TV464N2M.js} +13 -10
- package/dist/{chunk-RUSSKG6G.js → chunk-X7NRHFZR.js} +1 -1
- package/dist/{chunk-2BPG2XDA.js → chunk-XJVTQUIV.js} +18 -36
- package/dist/{chunk-ZVL7TY4K.js → chunk-YW6HQKGO.js} +25 -10
- 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 +29 -9
- package/dist/data.d.cts +23 -4
- package/dist/data.d.ts +23 -4
- 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 +672 -269
- package/dist/extras.d.cts +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/extras.js +24 -23
- package/dist/index.cjs +490 -88
- package/dist/index.d.cts +34 -2
- package/dist/index.d.ts +34 -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 +571 -240
- package/dist/plugins.d.cts +14 -3
- package/dist/plugins.d.ts +14 -3
- package/dist/plugins.js +35 -37
- 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 +484 -138
- package/dist/ssr.d.cts +59 -5
- package/dist/ssr.d.ts +59 -5
- package/dist/ssr.js +11 -9
- package/dist/testing.cjs +3 -3
- package/dist/testing.js +4 -4
- package/dist/ui.cjs +609 -241
- 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/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,
|
|
@@ -533,6 +534,11 @@ function checkLeaks(warnThreshold = 0) {
|
|
|
533
534
|
function stripControlChars(value) {
|
|
534
535
|
return value.replace(/[\x00-\x20\x7f-\x9f]+/g, "");
|
|
535
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
|
+
}
|
|
536
542
|
function isEventHandlerAttr(name) {
|
|
537
543
|
if (name.length < 3) return false;
|
|
538
544
|
const lower = name.toLowerCase();
|
|
@@ -544,6 +550,9 @@ function sanitizeUrl(url) {
|
|
|
544
550
|
const probe = stripControlChars(url).trim();
|
|
545
551
|
if (!probe) return "";
|
|
546
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
|
+
}
|
|
547
556
|
const lower = probe.toLowerCase();
|
|
548
557
|
let schemeEnd = -1;
|
|
549
558
|
for (let i2 = 0; i2 < lower.length; i2++) {
|
|
@@ -560,19 +569,58 @@ function sanitizeUrl(url) {
|
|
|
560
569
|
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
561
570
|
return output2;
|
|
562
571
|
}
|
|
563
|
-
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
|
+
}
|
|
564
576
|
function sanitizeSrcset(value) {
|
|
565
|
-
const
|
|
577
|
+
const input2 = String(value);
|
|
566
578
|
const out = [];
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
if (
|
|
572
|
-
|
|
573
|
-
|
|
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);
|
|
574
621
|
if (!safe) continue;
|
|
575
|
-
|
|
622
|
+
if (safe.startsWith(",") || safe.endsWith(",")) continue;
|
|
623
|
+
out.push(descriptors.length === 1 ? `${safe} ${descriptors[0]}` : safe);
|
|
576
624
|
}
|
|
577
625
|
return out.join(", ");
|
|
578
626
|
}
|
|
@@ -631,8 +679,16 @@ var BLOCKED_CSS_NEEDLES = [
|
|
|
631
679
|
"behavior:",
|
|
632
680
|
"@import",
|
|
633
681
|
"image-set(",
|
|
634
|
-
"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("
|
|
635
688
|
];
|
|
689
|
+
var CSS_REASON_MOZ_BINDING = 4;
|
|
690
|
+
var CSS_REASON_BEHAVIOR = 5;
|
|
691
|
+
var CSS_REASON_PROGID = 8;
|
|
636
692
|
function describeElement(el) {
|
|
637
693
|
if (!el) return "an element";
|
|
638
694
|
let out = el.tagName.toLowerCase();
|
|
@@ -656,7 +712,9 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
656
712
|
"behavior: loads and runs a remote HTC script",
|
|
657
713
|
"@import pulls in a remote stylesheet",
|
|
658
714
|
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
659
|
-
"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()"
|
|
660
718
|
];
|
|
661
719
|
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
662
720
|
const where = describeElement(ctx?.element);
|
|
@@ -671,27 +729,110 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
671
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.`;
|
|
672
730
|
});
|
|
673
731
|
}
|
|
732
|
+
function normalizeCssForScan(value) {
|
|
733
|
+
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
734
|
+
return normalized.toLowerCase().replace(/\s+/g, "");
|
|
735
|
+
}
|
|
674
736
|
function blockedCssReason(value) {
|
|
675
737
|
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
676
|
-
const
|
|
677
|
-
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
738
|
+
const lower = normalizeCssForScan(value);
|
|
678
739
|
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
679
740
|
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
680
741
|
}
|
|
681
742
|
return -1;
|
|
682
743
|
}
|
|
683
|
-
function
|
|
684
|
-
const reason =
|
|
744
|
+
function sanitizeCSSDeclaration(property, value, context2) {
|
|
745
|
+
const reason = blockedDeclarationReason(property, value);
|
|
685
746
|
if (reason === -1) return value;
|
|
686
|
-
warnDroppedDeclaration(value, reason, context2);
|
|
747
|
+
warnDroppedDeclaration(value, reason, { property, element: context2?.element });
|
|
687
748
|
return "";
|
|
688
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
|
+
}
|
|
689
832
|
function sanitizeStyleAttribute(cssText, context2) {
|
|
690
833
|
const input2 = String(cssText);
|
|
691
834
|
if (input2.trim() === "") return "";
|
|
692
|
-
if (typeof document === "undefined")
|
|
693
|
-
return sanitizeCSSValue(input2, context2) === "" ? "" : input2;
|
|
694
|
-
}
|
|
835
|
+
if (typeof document === "undefined") return sanitizeStyleDeclarationList(input2, context2);
|
|
695
836
|
const probe = document.createElement("div");
|
|
696
837
|
try {
|
|
697
838
|
probe.style.cssText = input2;
|
|
@@ -702,8 +843,7 @@ function sanitizeStyleAttribute(cssText, context2) {
|
|
|
702
843
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
703
844
|
const property = probe.style[i2];
|
|
704
845
|
const value = probe.style.getPropertyValue(property);
|
|
705
|
-
|
|
706
|
-
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
846
|
+
const reason = blockedDeclarationReason(property, value);
|
|
707
847
|
if (reason !== -1) {
|
|
708
848
|
warnDroppedDeclaration(value, reason, { property, element: context2?.element });
|
|
709
849
|
continue;
|
|
@@ -735,6 +875,13 @@ var HTML_CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set(["srcdoc"]);
|
|
|
735
875
|
function isHtmlContentAttribute(name) {
|
|
736
876
|
return HTML_CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
737
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
|
+
}
|
|
738
885
|
function sanitizeAttributeString(attr, value, context2) {
|
|
739
886
|
const lower = attr.toLowerCase();
|
|
740
887
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
@@ -742,27 +889,233 @@ function sanitizeAttributeString(attr, value, context2) {
|
|
|
742
889
|
if (lower === "style") return sanitizeStyleAttribute(value, context2);
|
|
743
890
|
return value;
|
|
744
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
|
+
}
|
|
745
897
|
|
|
746
|
-
// 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
|
|
747
972
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
748
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";
|
|
749
1084
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
750
1085
|
var XML_NS = "http://www.w3.org/XML/1998/namespace";
|
|
751
1086
|
var BOOLEAN_IDL_ATTRS = /* @__PURE__ */ new Set(["checked", "disabled", "selected"]);
|
|
752
1087
|
function isHtmlElement(el) {
|
|
753
|
-
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
|
+
});
|
|
754
1102
|
}
|
|
755
1103
|
function setProp(el, key, val) {
|
|
756
1104
|
el[key] = val;
|
|
757
1105
|
}
|
|
758
1106
|
function namespaceFor(el, name) {
|
|
759
|
-
if (el.namespaceURI !==
|
|
1107
|
+
if (el.namespaceURI !== SVG_NS2) return null;
|
|
760
1108
|
const lower = name.toLowerCase();
|
|
761
1109
|
if (lower.startsWith("xlink:")) return XLINK_NS;
|
|
762
1110
|
if (lower.startsWith("xml:")) return XML_NS;
|
|
763
1111
|
return null;
|
|
764
1112
|
}
|
|
765
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) {
|
|
766
1119
|
const ns = namespaceFor(el, name);
|
|
767
1120
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
768
1121
|
if (isEventHandlerAttr(name)) {
|
|
@@ -775,6 +1128,14 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
775
1128
|
else el.removeAttribute(name);
|
|
776
1129
|
return false;
|
|
777
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
|
+
}
|
|
778
1139
|
if (value == null) {
|
|
779
1140
|
if (ns) el.removeAttributeNS(ns, localName);
|
|
780
1141
|
else el.removeAttribute(name);
|
|
@@ -818,13 +1179,32 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
818
1179
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
819
1180
|
return true;
|
|
820
1181
|
}
|
|
821
|
-
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
|
+
}
|
|
822
1188
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
823
1189
|
if (current === safe) return true;
|
|
824
1190
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
825
1191
|
else el.setAttribute(name, safe);
|
|
826
1192
|
return true;
|
|
827
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
|
+
}
|
|
828
1208
|
|
|
829
1209
|
// src/reactivity/track-core.ts
|
|
830
1210
|
var POOL_MAX = 4096;
|
|
@@ -1317,7 +1697,7 @@ function forEachSubscriber(signal2, visit) {
|
|
|
1317
1697
|
}
|
|
1318
1698
|
|
|
1319
1699
|
// src/reactivity/track.ts
|
|
1320
|
-
var _runtimeVersion = true ? "4.
|
|
1700
|
+
var _runtimeVersion = true ? "4.9.0" : "dev";
|
|
1321
1701
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
1322
1702
|
function resolveReactiveApi() {
|
|
1323
1703
|
const g2 = globalThis;
|
|
@@ -1388,7 +1768,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
1388
1768
|
reportError(err, { phase: "binding", name: `bindAttribute("${attr}")`, node: el });
|
|
1389
1769
|
return;
|
|
1390
1770
|
}
|
|
1391
|
-
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")
|
|
1771
|
+
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")`, reactive: true });
|
|
1392
1772
|
}
|
|
1393
1773
|
return reactiveBinding2(commit, el);
|
|
1394
1774
|
}
|
|
@@ -1413,7 +1793,7 @@ function bindDynamic(el, nameGetter, valueGetter) {
|
|
|
1413
1793
|
el.removeAttribute(prevName);
|
|
1414
1794
|
prevName = null;
|
|
1415
1795
|
}
|
|
1416
|
-
if (!setSafeAttribute(el, name, value, { label: "bindDynamic" })) return;
|
|
1796
|
+
if (!setSafeAttribute(el, name, value, { label: "bindDynamic", reactive: true })) return;
|
|
1417
1797
|
prevName = name;
|
|
1418
1798
|
}
|
|
1419
1799
|
const teardown = reactiveBinding2(commit, el);
|
|
@@ -1594,11 +1974,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
1594
1974
|
}
|
|
1595
1975
|
|
|
1596
1976
|
// src/core/rendering/tagFactory.ts
|
|
1597
|
-
var
|
|
1598
|
-
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
1599
|
-
function isBlockedTag(tag) {
|
|
1600
|
-
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
1601
|
-
}
|
|
1977
|
+
var SVG_NS3 = "http://www.w3.org/2000/svg";
|
|
1602
1978
|
var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
1603
1979
|
"config",
|
|
1604
1980
|
"location",
|
|
@@ -1643,11 +2019,12 @@ function applyStyle(el, style2) {
|
|
|
1643
2019
|
}
|
|
1644
2020
|
const next = [];
|
|
1645
2021
|
for (const prop in value) {
|
|
2022
|
+
if (!Object.hasOwn(value, prop)) continue;
|
|
1646
2023
|
const val = value[prop];
|
|
1647
2024
|
if (val == null) continue;
|
|
1648
2025
|
const name = toKebab(prop);
|
|
1649
2026
|
next.push(name);
|
|
1650
|
-
decl.setProperty(name,
|
|
2027
|
+
decl.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
1651
2028
|
}
|
|
1652
2029
|
for (let i2 = 0; i2 < written.length; i2++) {
|
|
1653
2030
|
if (next.indexOf(written[i2]) === -1) decl.removeProperty(written[i2]);
|
|
@@ -1663,16 +2040,17 @@ function applyStyle(el, style2) {
|
|
|
1663
2040
|
}
|
|
1664
2041
|
const htmlEl = el;
|
|
1665
2042
|
for (const prop in style2) {
|
|
2043
|
+
if (!Object.hasOwn(style2, prop)) continue;
|
|
1666
2044
|
const val = style2[prop];
|
|
1667
2045
|
const name = toKebab(prop);
|
|
1668
2046
|
if (typeof val === "function") {
|
|
1669
2047
|
const getter = val;
|
|
1670
2048
|
const teardown = reactiveBinding2(() => {
|
|
1671
|
-
htmlEl.style.setProperty(name,
|
|
2049
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(getter()), { element: el }));
|
|
1672
2050
|
}, el);
|
|
1673
2051
|
registerDisposer(el, teardown);
|
|
1674
2052
|
} else {
|
|
1675
|
-
htmlEl.style.setProperty(name,
|
|
2053
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
1676
2054
|
}
|
|
1677
2055
|
}
|
|
1678
2056
|
}
|
|
@@ -1694,6 +2072,7 @@ function applyClass(el, cls) {
|
|
|
1694
2072
|
let hasReactive = false;
|
|
1695
2073
|
let result = "";
|
|
1696
2074
|
for (const name in obj) {
|
|
2075
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
1697
2076
|
const val = obj[name];
|
|
1698
2077
|
if (typeof val === "function") {
|
|
1699
2078
|
hasReactive = true;
|
|
@@ -1705,6 +2084,7 @@ function applyClass(el, cls) {
|
|
|
1705
2084
|
const update = () => {
|
|
1706
2085
|
let r = "";
|
|
1707
2086
|
for (const name in obj) {
|
|
2087
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
1708
2088
|
const val = obj[name];
|
|
1709
2089
|
const active = typeof val === "function" ? val() : val;
|
|
1710
2090
|
if (active) r = r ? `${r} ${name}` : name;
|
|
@@ -1768,7 +2148,7 @@ function appendChildren(el, nodes) {
|
|
|
1768
2148
|
}
|
|
1769
2149
|
}
|
|
1770
2150
|
function tagFactory(tag, ns) {
|
|
1771
|
-
const blocked =
|
|
2151
|
+
const blocked = isBlockedElement(tag);
|
|
1772
2152
|
return (first, second) => {
|
|
1773
2153
|
if (blocked) {
|
|
1774
2154
|
throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
@@ -1831,6 +2211,7 @@ function tagFactory(tag, ns) {
|
|
|
1831
2211
|
const pOn = props.on;
|
|
1832
2212
|
if (pOn) {
|
|
1833
2213
|
for (const ev in pOn) {
|
|
2214
|
+
if (!Object.hasOwn(pOn, ev)) continue;
|
|
1834
2215
|
const handler = pOn[ev];
|
|
1835
2216
|
if (typeof handler === "function") {
|
|
1836
2217
|
el.addEventListener(ev, handler);
|
|
@@ -1857,6 +2238,7 @@ function tagFactory(tag, ns) {
|
|
|
1857
2238
|
continue;
|
|
1858
2239
|
// already handled above / below
|
|
1859
2240
|
default: {
|
|
2241
|
+
if (!Object.hasOwn(props, key)) continue;
|
|
1860
2242
|
const value = props[key];
|
|
1861
2243
|
if (value == null) continue;
|
|
1862
2244
|
if (isEventHandlerAttr(key)) continue;
|
|
@@ -1946,7 +2328,7 @@ var param = tagFactory("param");
|
|
|
1946
2328
|
var picture = tagFactory("picture");
|
|
1947
2329
|
var portal = tagFactory("portal");
|
|
1948
2330
|
var source = tagFactory("source");
|
|
1949
|
-
var svg = tagFactory("svg",
|
|
2331
|
+
var svg = tagFactory("svg", SVG_NS3);
|
|
1950
2332
|
var math = tagFactory("math");
|
|
1951
2333
|
var canvas = tagFactory("canvas");
|
|
1952
2334
|
var noscript = tagFactory("noscript");
|
|
@@ -1987,26 +2369,26 @@ var base = tagFactory("base");
|
|
|
1987
2369
|
var link = tagFactory("link");
|
|
1988
2370
|
var meta = tagFactory("meta");
|
|
1989
2371
|
var style = tagFactory("style");
|
|
1990
|
-
var circle = tagFactory("circle",
|
|
1991
|
-
var ellipse = tagFactory("ellipse",
|
|
1992
|
-
var g = tagFactory("g",
|
|
1993
|
-
var line = tagFactory("line",
|
|
1994
|
-
var path = tagFactory("path",
|
|
1995
|
-
var polygon = tagFactory("polygon",
|
|
1996
|
-
var polyline = tagFactory("polyline",
|
|
1997
|
-
var rect = tagFactory("rect",
|
|
1998
|
-
var text = tagFactory("text",
|
|
1999
|
-
var tspan = tagFactory("tspan",
|
|
2000
|
-
var defs = tagFactory("defs",
|
|
2001
|
-
var clipPath = tagFactory("clipPath",
|
|
2002
|
-
var mask = tagFactory("mask",
|
|
2003
|
-
var pattern = tagFactory("pattern",
|
|
2004
|
-
var linearGradient = tagFactory("linearGradient",
|
|
2005
|
-
var radialGradient = tagFactory("radialGradient",
|
|
2006
|
-
var stop = tagFactory("stop",
|
|
2007
|
-
var use = tagFactory("use",
|
|
2008
|
-
var symbol = tagFactory("symbol",
|
|
2009
|
-
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);
|
|
2010
2392
|
var center = tagFactory("center");
|
|
2011
2393
|
var font = tagFactory("font");
|
|
2012
2394
|
var marquee = tagFactory("marquee");
|
|
@@ -3584,37 +3966,44 @@ function action(element, action2, param2) {
|
|
|
3584
3966
|
}
|
|
3585
3967
|
}
|
|
3586
3968
|
var clickOutside = (element, callback) => {
|
|
3969
|
+
const doc = element.ownerDocument;
|
|
3587
3970
|
const handler = (e) => {
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
}
|
|
3971
|
+
const target = e.target;
|
|
3972
|
+
if (!(typeof target?.nodeType === "number" && element.contains(target))) callback();
|
|
3591
3973
|
};
|
|
3592
|
-
|
|
3593
|
-
return () =>
|
|
3974
|
+
doc.addEventListener("pointerdown", handler, true);
|
|
3975
|
+
return () => doc.removeEventListener("pointerdown", handler, true);
|
|
3594
3976
|
};
|
|
3977
|
+
var PRESS_END_EVENTS = ["pointerup", "pointerleave", "pointercancel"];
|
|
3595
3978
|
var longPress = (element, options) => {
|
|
3596
3979
|
const duration = options.duration ?? 500;
|
|
3597
3980
|
let timer = null;
|
|
3598
|
-
|
|
3599
|
-
timer = setTimeout(() => {
|
|
3600
|
-
options.callback();
|
|
3601
|
-
timer = null;
|
|
3602
|
-
}, duration);
|
|
3603
|
-
};
|
|
3981
|
+
let owner;
|
|
3604
3982
|
const cancel = () => {
|
|
3605
3983
|
if (timer !== null) {
|
|
3606
3984
|
clearTimeout(timer);
|
|
3607
3985
|
timer = null;
|
|
3608
3986
|
}
|
|
3609
3987
|
};
|
|
3988
|
+
const start = (e) => {
|
|
3989
|
+
const id = e.pointerId;
|
|
3990
|
+
if (timer !== null && id !== owner) return;
|
|
3991
|
+
cancel();
|
|
3992
|
+
owner = id;
|
|
3993
|
+
timer = setTimeout(() => {
|
|
3994
|
+
timer = null;
|
|
3995
|
+
options.callback();
|
|
3996
|
+
}, duration);
|
|
3997
|
+
};
|
|
3998
|
+
const end = (e) => {
|
|
3999
|
+
if (timer !== null && e.pointerId === owner) cancel();
|
|
4000
|
+
};
|
|
3610
4001
|
element.addEventListener("pointerdown", start);
|
|
3611
|
-
element.addEventListener(
|
|
3612
|
-
element.addEventListener("pointerleave", cancel);
|
|
4002
|
+
for (const type of PRESS_END_EVENTS) element.addEventListener(type, end);
|
|
3613
4003
|
return () => {
|
|
3614
4004
|
cancel();
|
|
3615
4005
|
element.removeEventListener("pointerdown", start);
|
|
3616
|
-
element.removeEventListener(
|
|
3617
|
-
element.removeEventListener("pointerleave", cancel);
|
|
4006
|
+
for (const type of PRESS_END_EVENTS) element.removeEventListener(type, end);
|
|
3618
4007
|
};
|
|
3619
4008
|
};
|
|
3620
4009
|
var copyOnClick = (element, getText) => {
|
|
@@ -3648,10 +4037,11 @@ var trapFocus = (element) => {
|
|
|
3648
4037
|
if (elements.length === 0) return;
|
|
3649
4038
|
const first = elements[0];
|
|
3650
4039
|
const last = elements[elements.length - 1];
|
|
3651
|
-
|
|
4040
|
+
const active = element.ownerDocument.activeElement;
|
|
4041
|
+
if (e.shiftKey && active === first) {
|
|
3652
4042
|
e.preventDefault();
|
|
3653
4043
|
last.focus();
|
|
3654
|
-
} else if (!e.shiftKey &&
|
|
4044
|
+
} else if (!e.shiftKey && active === last) {
|
|
3655
4045
|
e.preventDefault();
|
|
3656
4046
|
first.focus();
|
|
3657
4047
|
}
|
|
@@ -3820,6 +4210,10 @@ function attachBranch(parent, anchor, branch, attachedOnce, where) {
|
|
|
3820
4210
|
parent.insertBefore(node, anchor.nextSibling);
|
|
3821
4211
|
return { node, owned };
|
|
3822
4212
|
}
|
|
4213
|
+
function releaseBranchNode(node, owned) {
|
|
4214
|
+
if (owned) dispose(node);
|
|
4215
|
+
node.parentNode?.removeChild(node);
|
|
4216
|
+
}
|
|
3823
4217
|
function when(condition, thenBranch, elseBranch) {
|
|
3824
4218
|
const anchor = document.createComment("when");
|
|
3825
4219
|
let currentNode = null;
|
|
@@ -3837,8 +4231,7 @@ function when(condition, thenBranch, elseBranch) {
|
|
|
3837
4231
|
lastCondition = show2;
|
|
3838
4232
|
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
3839
4233
|
if (currentNode?.parentNode) {
|
|
3840
|
-
|
|
3841
|
-
currentNode.parentNode.removeChild(currentNode);
|
|
4234
|
+
releaseBranchNode(currentNode, currentNodeOwned);
|
|
3842
4235
|
currentNode = null;
|
|
3843
4236
|
}
|
|
3844
4237
|
const branch = show2 ? thenBranch : elseBranch !== void 0 ? elseBranch : null;
|
|
@@ -3852,6 +4245,8 @@ function when(condition, thenBranch, elseBranch) {
|
|
|
3852
4245
|
registerDisposer(anchor, () => {
|
|
3853
4246
|
disposed = true;
|
|
3854
4247
|
stopBinding();
|
|
4248
|
+
if (currentNode) releaseBranchNode(currentNode, currentNodeOwned);
|
|
4249
|
+
currentNode = null;
|
|
3855
4250
|
});
|
|
3856
4251
|
if (!initialized) {
|
|
3857
4252
|
queueMicrotask(() => {
|
|
@@ -3877,8 +4272,7 @@ function match(value, cases, fallback) {
|
|
|
3877
4272
|
lastKey = key;
|
|
3878
4273
|
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
3879
4274
|
if (currentNode?.parentNode) {
|
|
3880
|
-
|
|
3881
|
-
currentNode.parentNode.removeChild(currentNode);
|
|
4275
|
+
releaseBranchNode(currentNode, currentNodeOwned);
|
|
3882
4276
|
currentNode = null;
|
|
3883
4277
|
}
|
|
3884
4278
|
const branch = Object.hasOwn(cases, key) ? cases[key] : fallback;
|
|
@@ -3892,6 +4286,8 @@ function match(value, cases, fallback) {
|
|
|
3892
4286
|
registerDisposer(anchor, () => {
|
|
3893
4287
|
disposed = true;
|
|
3894
4288
|
stopBinding();
|
|
4289
|
+
if (currentNode) releaseBranchNode(currentNode, currentNodeOwned);
|
|
4290
|
+
currentNode = null;
|
|
3895
4291
|
});
|
|
3896
4292
|
if (!initialized) {
|
|
3897
4293
|
queueMicrotask(() => {
|
|
@@ -4234,7 +4630,6 @@ function appendChild(frag, child) {
|
|
|
4234
4630
|
}
|
|
4235
4631
|
|
|
4236
4632
|
// src/core/rendering/htm.ts
|
|
4237
|
-
var RAW_TEXT_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
4238
4633
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
4239
4634
|
"area",
|
|
4240
4635
|
"base",
|
|
@@ -4457,7 +4852,7 @@ function parseTemplate(strings) {
|
|
|
4457
4852
|
children.push({ t: 0, el: { tag, svg: SVG_TAGS.has(tag), attrs, children: [] } });
|
|
4458
4853
|
} else {
|
|
4459
4854
|
const inner = parseChildren();
|
|
4460
|
-
if (
|
|
4855
|
+
if (isCodeTextElement(tag)) {
|
|
4461
4856
|
for (let i2 = 0; i2 < inner.length; i2++) {
|
|
4462
4857
|
if (inner[i2].t === 2) {
|
|
4463
4858
|
throw new Error(
|
|
@@ -4483,12 +4878,12 @@ function parseTemplate(strings) {
|
|
|
4483
4878
|
return parseChildren();
|
|
4484
4879
|
}
|
|
4485
4880
|
function executeElement(tmpl, values) {
|
|
4486
|
-
const el = tmpl.svg ? document.createElementNS(
|
|
4881
|
+
const el = tmpl.svg ? document.createElementNS(SVG_NS3, tmpl.tag) : document.createElement(tmpl.tag);
|
|
4487
4882
|
for (let i2 = 0; i2 < tmpl.attrs.length; i2++) {
|
|
4488
4883
|
const attr = tmpl.attrs[i2];
|
|
4489
4884
|
switch (attr.t) {
|
|
4490
4885
|
case 0:
|
|
4491
|
-
el
|
|
4886
|
+
setTrustedAttribute(el, attr.name, attr.value);
|
|
4492
4887
|
break;
|
|
4493
4888
|
case 1: {
|
|
4494
4889
|
const name = attr.name;
|
|
@@ -4521,7 +4916,7 @@ function executeElement(tmpl, values) {
|
|
|
4521
4916
|
break;
|
|
4522
4917
|
}
|
|
4523
4918
|
case 4:
|
|
4524
|
-
el
|
|
4919
|
+
setTrustedAttribute(el, attr.name, "");
|
|
4525
4920
|
break;
|
|
4526
4921
|
}
|
|
4527
4922
|
}
|
|
@@ -4566,6 +4961,12 @@ function html2(strings, ...values) {
|
|
|
4566
4961
|
tmpl = parseTemplate(strings);
|
|
4567
4962
|
cache.set(strings, tmpl);
|
|
4568
4963
|
}
|
|
4964
|
+
return renderTemplate(tmpl, values);
|
|
4965
|
+
}
|
|
4966
|
+
function __renderParsedTemplate(tree, values) {
|
|
4967
|
+
return renderTemplate(tree, values);
|
|
4968
|
+
}
|
|
4969
|
+
function renderTemplate(tmpl, values) {
|
|
4569
4970
|
if (tmpl.length === 1 && tmpl[0].t === 0) {
|
|
4570
4971
|
return executeElement(tmpl[0].el, values);
|
|
4571
4972
|
}
|
|
@@ -4641,7 +5042,7 @@ function KeepAlive(activeKey, cases, options) {
|
|
|
4641
5042
|
return;
|
|
4642
5043
|
}
|
|
4643
5044
|
node = factory();
|
|
4644
|
-
if (node
|
|
5045
|
+
if (node.nodeType === 11) {
|
|
4645
5046
|
const wrapper = document.createElement("div");
|
|
4646
5047
|
wrapper.style.display = "contents";
|
|
4647
5048
|
wrapper.appendChild(node);
|
|
@@ -5654,7 +6055,7 @@ function enhance(target, setup) {
|
|
|
5654
6055
|
bindNode(el, () => {
|
|
5655
6056
|
const v = value();
|
|
5656
6057
|
const next = v == null ? null : String(v);
|
|
5657
|
-
setSafeAttribute(el, name, next, { syncValueProperty: false, label: "enhance attr()" });
|
|
6058
|
+
setSafeAttribute(el, name, next, { syncValueProperty: false, label: "enhance attr()", reactive: true });
|
|
5658
6059
|
})
|
|
5659
6060
|
);
|
|
5660
6061
|
});
|
|
@@ -6026,6 +6427,7 @@ function nextTick() {
|
|
|
6026
6427
|
Portal,
|
|
6027
6428
|
SVG_NS,
|
|
6028
6429
|
Suspense,
|
|
6430
|
+
__renderParsedTemplate,
|
|
6029
6431
|
__resetIdCounter,
|
|
6030
6432
|
a,
|
|
6031
6433
|
abbr,
|