sibujs 4.7.0 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.cjs +45 -4
- package/dist/browser.d.cts +23 -0
- package/dist/browser.d.ts +23 -0
- package/dist/browser.js +6 -5
- package/dist/build.cjs +513 -78
- package/dist/build.d.cts +22 -8
- package/dist/build.d.ts +22 -8
- package/dist/build.js +68 -21
- package/dist/cdn.dev.global.js +15 -13
- package/dist/cdn.full.dev.global.js +15 -13
- package/dist/cdn.full.global.js +14 -12
- package/dist/cdn.global.js +14 -12
- package/dist/chunk-3ACAAQIN.js +224 -0
- package/dist/{chunk-DKXRACVN.js → chunk-44MTL7ED.js} +6 -6
- package/dist/{chunk-3QWBSL5R.js → chunk-4WMSTZ7J.js} +8 -5
- package/dist/{chunk-H3SRKIYX.js → chunk-62BDYGAG.js} +8 -0
- package/dist/{chunk-BSY63EM6.js → chunk-C5PEWEGH.js} +20 -5
- package/dist/{chunk-BC2SECJD.js → chunk-C7AA2CZX.js} +1 -1
- package/dist/{chunk-SLM3IA34.js → chunk-CZPRSWSS.js} +1 -1
- package/dist/{chunk-FQRUXCEE.js → chunk-DSID757X.js} +1 -1
- package/dist/{chunk-ZVL7TY4K.js → chunk-EGUQLBHE.js} +22 -8
- package/dist/{chunk-2INLLLMZ.js → chunk-EXXSN3BW.js} +202 -26
- package/dist/{chunk-HURREPU2.js → chunk-FC6KCJSA.js} +87 -150
- package/dist/{chunk-Z3OHK6QT.js → chunk-GSGNX35Q.js} +5 -5
- package/dist/{chunk-XYV3EDB7.js → chunk-J3YQ457H.js} +37 -20
- package/dist/{chunk-VZSG24LS.js → chunk-JUTFX2RM.js} +18 -10
- package/dist/{chunk-RUSSKG6G.js → chunk-KJ3UKABJ.js} +1 -1
- package/dist/{chunk-UNWRJRKC.js → chunk-LI4W3U6C.js} +1 -1
- package/dist/{chunk-FNJXNGYZ.js → chunk-O6TRVMJI.js} +58 -6
- package/dist/{chunk-7LUJQAOJ.js → chunk-Q5J2LVKH.js} +1 -1
- package/dist/{chunk-4AWA2PVD.js → chunk-QGMSESDD.js} +10 -5
- package/dist/{chunk-XZR4PXRE.js → chunk-RGLPEBDE.js} +13 -10
- package/dist/{chunk-JWKYU5GV.js → chunk-TQQUN4WR.js} +1 -1
- package/dist/{chunk-WOLJZUFQ.js → chunk-UCNP3HVM.js} +12 -8
- package/dist/{chunk-WEQ3DMVL.js → chunk-V3LHZSU5.js} +1 -1
- package/dist/{chunk-UOL2ECCS.js → chunk-VWT3VXPL.js} +18 -12
- package/dist/{chunk-2BPG2XDA.js → chunk-ZVLHNEEL.js} +17 -35
- package/dist/{customElement-MmInOW1U.d.ts → customElement-pYDKUzWl.d.cts} +11 -3
- package/dist/{customElement-MmInOW1U.d.cts → customElement-pYDKUzWl.d.ts} +11 -3
- package/dist/data.cjs +9 -2
- package/dist/data.js +6 -6
- package/dist/devtools.cjs +1 -1
- package/dist/devtools.js +5 -5
- package/dist/ecosystem.cjs +400 -37
- package/dist/ecosystem.js +9 -8
- package/dist/extras.cjs +621 -252
- package/dist/extras.d.cts +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/extras.js +24 -23
- package/dist/index.cjs +464 -70
- package/dist/index.d.cts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +16 -12
- package/dist/motion.cjs +1 -1
- package/dist/motion.js +3 -3
- package/dist/patterns.cjs +10 -7
- package/dist/patterns.js +6 -6
- package/dist/performance.cjs +31 -2
- package/dist/performance.d.cts +12 -2
- package/dist/performance.d.ts +12 -2
- package/dist/performance.js +8 -6
- package/dist/plugins.cjs +558 -231
- package/dist/plugins.d.cts +8 -3
- package/dist/plugins.d.ts +8 -3
- package/dist/plugins.js +22 -28
- package/dist/{ssr-XOTUASDO.js → ssr-5OWAH3U2.js} +4 -2
- package/dist/{ssr-Bli9XRW5.d.ts → ssr-C8hgIAw7.d.cts} +6 -0
- package/dist/{ssr-Bli9XRW5.d.cts → ssr-C8hgIAw7.d.ts} +6 -0
- package/dist/ssr.cjs +457 -131
- package/dist/ssr.d.cts +55 -5
- package/dist/ssr.d.ts +55 -5
- package/dist/ssr.js +11 -9
- package/dist/testing.cjs +3 -3
- package/dist/testing.js +4 -4
- package/dist/ui.cjs +608 -240
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +9 -8
- package/dist/widgets.cjs +1 -1
- package/dist/widgets.js +7 -7
- package/package.json +5 -4
package/dist/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.8.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");
|
|
@@ -3820,6 +4202,10 @@ function attachBranch(parent, anchor, branch, attachedOnce, where) {
|
|
|
3820
4202
|
parent.insertBefore(node, anchor.nextSibling);
|
|
3821
4203
|
return { node, owned };
|
|
3822
4204
|
}
|
|
4205
|
+
function releaseBranchNode(node, owned) {
|
|
4206
|
+
if (owned) dispose(node);
|
|
4207
|
+
node.parentNode?.removeChild(node);
|
|
4208
|
+
}
|
|
3823
4209
|
function when(condition, thenBranch, elseBranch) {
|
|
3824
4210
|
const anchor = document.createComment("when");
|
|
3825
4211
|
let currentNode = null;
|
|
@@ -3837,8 +4223,7 @@ function when(condition, thenBranch, elseBranch) {
|
|
|
3837
4223
|
lastCondition = show2;
|
|
3838
4224
|
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
3839
4225
|
if (currentNode?.parentNode) {
|
|
3840
|
-
|
|
3841
|
-
currentNode.parentNode.removeChild(currentNode);
|
|
4226
|
+
releaseBranchNode(currentNode, currentNodeOwned);
|
|
3842
4227
|
currentNode = null;
|
|
3843
4228
|
}
|
|
3844
4229
|
const branch = show2 ? thenBranch : elseBranch !== void 0 ? elseBranch : null;
|
|
@@ -3852,6 +4237,8 @@ function when(condition, thenBranch, elseBranch) {
|
|
|
3852
4237
|
registerDisposer(anchor, () => {
|
|
3853
4238
|
disposed = true;
|
|
3854
4239
|
stopBinding();
|
|
4240
|
+
if (currentNode) releaseBranchNode(currentNode, currentNodeOwned);
|
|
4241
|
+
currentNode = null;
|
|
3855
4242
|
});
|
|
3856
4243
|
if (!initialized) {
|
|
3857
4244
|
queueMicrotask(() => {
|
|
@@ -3877,8 +4264,7 @@ function match(value, cases, fallback) {
|
|
|
3877
4264
|
lastKey = key;
|
|
3878
4265
|
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
3879
4266
|
if (currentNode?.parentNode) {
|
|
3880
|
-
|
|
3881
|
-
currentNode.parentNode.removeChild(currentNode);
|
|
4267
|
+
releaseBranchNode(currentNode, currentNodeOwned);
|
|
3882
4268
|
currentNode = null;
|
|
3883
4269
|
}
|
|
3884
4270
|
const branch = Object.hasOwn(cases, key) ? cases[key] : fallback;
|
|
@@ -3892,6 +4278,8 @@ function match(value, cases, fallback) {
|
|
|
3892
4278
|
registerDisposer(anchor, () => {
|
|
3893
4279
|
disposed = true;
|
|
3894
4280
|
stopBinding();
|
|
4281
|
+
if (currentNode) releaseBranchNode(currentNode, currentNodeOwned);
|
|
4282
|
+
currentNode = null;
|
|
3895
4283
|
});
|
|
3896
4284
|
if (!initialized) {
|
|
3897
4285
|
queueMicrotask(() => {
|
|
@@ -4234,7 +4622,6 @@ function appendChild(frag, child) {
|
|
|
4234
4622
|
}
|
|
4235
4623
|
|
|
4236
4624
|
// src/core/rendering/htm.ts
|
|
4237
|
-
var RAW_TEXT_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
4238
4625
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
4239
4626
|
"area",
|
|
4240
4627
|
"base",
|
|
@@ -4457,7 +4844,7 @@ function parseTemplate(strings) {
|
|
|
4457
4844
|
children.push({ t: 0, el: { tag, svg: SVG_TAGS.has(tag), attrs, children: [] } });
|
|
4458
4845
|
} else {
|
|
4459
4846
|
const inner = parseChildren();
|
|
4460
|
-
if (
|
|
4847
|
+
if (isCodeTextElement(tag)) {
|
|
4461
4848
|
for (let i2 = 0; i2 < inner.length; i2++) {
|
|
4462
4849
|
if (inner[i2].t === 2) {
|
|
4463
4850
|
throw new Error(
|
|
@@ -4483,12 +4870,12 @@ function parseTemplate(strings) {
|
|
|
4483
4870
|
return parseChildren();
|
|
4484
4871
|
}
|
|
4485
4872
|
function executeElement(tmpl, values) {
|
|
4486
|
-
const el = tmpl.svg ? document.createElementNS(
|
|
4873
|
+
const el = tmpl.svg ? document.createElementNS(SVG_NS3, tmpl.tag) : document.createElement(tmpl.tag);
|
|
4487
4874
|
for (let i2 = 0; i2 < tmpl.attrs.length; i2++) {
|
|
4488
4875
|
const attr = tmpl.attrs[i2];
|
|
4489
4876
|
switch (attr.t) {
|
|
4490
4877
|
case 0:
|
|
4491
|
-
el
|
|
4878
|
+
setTrustedAttribute(el, attr.name, attr.value);
|
|
4492
4879
|
break;
|
|
4493
4880
|
case 1: {
|
|
4494
4881
|
const name = attr.name;
|
|
@@ -4521,7 +4908,7 @@ function executeElement(tmpl, values) {
|
|
|
4521
4908
|
break;
|
|
4522
4909
|
}
|
|
4523
4910
|
case 4:
|
|
4524
|
-
el
|
|
4911
|
+
setTrustedAttribute(el, attr.name, "");
|
|
4525
4912
|
break;
|
|
4526
4913
|
}
|
|
4527
4914
|
}
|
|
@@ -4566,6 +4953,12 @@ function html2(strings, ...values) {
|
|
|
4566
4953
|
tmpl = parseTemplate(strings);
|
|
4567
4954
|
cache.set(strings, tmpl);
|
|
4568
4955
|
}
|
|
4956
|
+
return renderTemplate(tmpl, values);
|
|
4957
|
+
}
|
|
4958
|
+
function __renderParsedTemplate(tree, values) {
|
|
4959
|
+
return renderTemplate(tree, values);
|
|
4960
|
+
}
|
|
4961
|
+
function renderTemplate(tmpl, values) {
|
|
4569
4962
|
if (tmpl.length === 1 && tmpl[0].t === 0) {
|
|
4570
4963
|
return executeElement(tmpl[0].el, values);
|
|
4571
4964
|
}
|
|
@@ -5654,7 +6047,7 @@ function enhance(target, setup) {
|
|
|
5654
6047
|
bindNode(el, () => {
|
|
5655
6048
|
const v = value();
|
|
5656
6049
|
const next = v == null ? null : String(v);
|
|
5657
|
-
setSafeAttribute(el, name, next, { syncValueProperty: false, label: "enhance attr()" });
|
|
6050
|
+
setSafeAttribute(el, name, next, { syncValueProperty: false, label: "enhance attr()", reactive: true });
|
|
5658
6051
|
})
|
|
5659
6052
|
);
|
|
5660
6053
|
});
|
|
@@ -6026,6 +6419,7 @@ function nextTick() {
|
|
|
6026
6419
|
Portal,
|
|
6027
6420
|
SVG_NS,
|
|
6028
6421
|
Suspense,
|
|
6422
|
+
__renderParsedTemplate,
|
|
6029
6423
|
__resetIdCounter,
|
|
6030
6424
|
a,
|
|
6031
6425
|
abbr,
|