sibujs 4.6.0 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/browser.cjs +62 -8
- package/dist/browser.d.cts +23 -0
- package/dist/browser.d.ts +23 -0
- package/dist/browser.js +6 -5
- package/dist/build.cjs +2388 -1004
- package/dist/build.d.cts +147 -44
- package/dist/build.d.ts +147 -44
- package/dist/build.js +1410 -564
- package/dist/cdn.dev.global.js +14 -12
- package/dist/cdn.full.dev.global.js +15 -13
- package/dist/cdn.full.global.js +14 -12
- package/dist/cdn.global.js +12 -10
- package/dist/chunk-3ACAAQIN.js +224 -0
- package/dist/{chunk-7NCARGJW.js → chunk-44MTL7ED.js} +6 -6
- package/dist/{chunk-BAAG6ZTI.js → chunk-4WMSTZ7J.js} +8 -5
- package/dist/{chunk-H3SRKIYX.js → chunk-62BDYGAG.js} +8 -0
- package/dist/{chunk-DKGBBKOF.js → chunk-C5PEWEGH.js} +20 -5
- package/dist/{chunk-3ISI6ACU.js → chunk-C7AA2CZX.js} +1 -1
- package/dist/{chunk-UZQ6ALFS.js → chunk-CZPRSWSS.js} +1 -1
- package/dist/{chunk-D33YTSX5.js → chunk-DSID757X.js} +5 -4
- package/dist/{chunk-OXUY2A6L.js → chunk-EGUQLBHE.js} +22 -8
- package/dist/{chunk-2INLLLMZ.js → chunk-EXXSN3BW.js} +202 -26
- package/dist/{chunk-HURREPU2.js → chunk-FC6KCJSA.js} +87 -150
- package/dist/{chunk-HYXDKS4N.js → chunk-GSGNX35Q.js} +5 -5
- package/dist/{chunk-7GQCWFOE.js → chunk-J3YQ457H.js} +171 -85
- package/dist/{chunk-ORMZXBKQ.js → chunk-JUTFX2RM.js} +18 -10
- package/dist/{chunk-QE4TTDU3.js → chunk-KJ3UKABJ.js} +12 -11
- package/dist/{chunk-XRRZKZYX.js → chunk-LI4W3U6C.js} +1 -1
- package/dist/{chunk-47M47FOM.js → chunk-O6TRVMJI.js} +58 -6
- package/dist/{chunk-JSXPZCET.js → chunk-Q5J2LVKH.js} +1 -1
- package/dist/{chunk-5MT6SJ3P.js → chunk-QGMSESDD.js} +10 -5
- package/dist/{chunk-AIF3Z2T7.js → chunk-RGLPEBDE.js} +13 -10
- package/dist/{chunk-5Q4R7HCL.js → chunk-TQQUN4WR.js} +11 -2
- package/dist/{chunk-PK6FK2G2.js → chunk-UCNP3HVM.js} +183 -30
- package/dist/{chunk-XC4MEKGA.js → chunk-V3LHZSU5.js} +8 -2
- package/dist/{chunk-VVWPJ543.js → chunk-VWT3VXPL.js} +55 -20
- package/dist/{chunk-SXXVZMKZ.js → chunk-ZVLHNEEL.js} +17 -35
- package/dist/{contracts-DRIuclVT.d.cts → contracts-CLqzJnOV.d.ts} +28 -17
- package/dist/{contracts-DRIuclVT.d.ts → contracts-CTOJXu-x.d.cts} +28 -17
- package/dist/{customElement-MmInOW1U.d.ts → customElement-pYDKUzWl.d.cts} +11 -3
- package/dist/{customElement-MmInOW1U.d.cts → customElement-pYDKUzWl.d.ts} +11 -3
- package/dist/data.cjs +205 -39
- package/dist/data.d.cts +119 -3
- package/dist/data.d.ts +119 -3
- package/dist/data.js +6 -6
- package/dist/devtools.cjs +18 -5
- package/dist/devtools.js +5 -5
- package/dist/ecosystem.cjs +462 -58
- package/dist/ecosystem.d.cts +2 -1
- package/dist/ecosystem.d.ts +2 -1
- package/dist/ecosystem.js +9 -8
- package/dist/extras.cjs +852 -296
- package/dist/extras.d.cts +5 -4
- package/dist/extras.d.ts +5 -4
- package/dist/extras.js +24 -23
- package/dist/index.cjs +721 -176
- package/dist/index.d.cts +220 -169
- package/dist/index.d.ts +220 -169
- package/dist/index.js +16 -12
- package/dist/motion.cjs +12 -4
- package/dist/motion.js +3 -3
- package/dist/patterns.cjs +37 -21
- package/dist/patterns.d.cts +2 -1
- package/dist/patterns.d.ts +2 -1
- package/dist/patterns.js +6 -6
- package/dist/performance.cjs +48 -6
- package/dist/performance.d.cts +12 -2
- package/dist/performance.d.ts +12 -2
- package/dist/performance.js +8 -6
- package/dist/plugins.cjs +672 -261
- package/dist/plugins.d.cts +131 -13
- package/dist/plugins.d.ts +131 -13
- package/dist/plugins.js +83 -47
- package/dist/{ssr-XOTUASDO.js → ssr-5OWAH3U2.js} +4 -2
- package/dist/{ssr-Bli9XRW5.d.cts → ssr-C8hgIAw7.d.cts} +6 -0
- package/dist/{ssr-Bli9XRW5.d.ts → ssr-C8hgIAw7.d.ts} +6 -0
- package/dist/ssr.cjs +509 -142
- package/dist/ssr.d.cts +55 -5
- package/dist/ssr.d.ts +55 -5
- package/dist/ssr.js +11 -9
- package/dist/{tagFactory-DFstCLQV.d.cts → tagFactory-8qL9LCIx.d.cts} +58 -19
- package/dist/{tagFactory-DkaNVUNV.d.ts → tagFactory-BL2fymez.d.ts} +58 -19
- package/dist/testing.cjs +17 -4
- package/dist/testing.js +4 -4
- package/dist/types-CJFViL6Q.d.cts +26 -0
- package/dist/types-CJFViL6Q.d.ts +26 -0
- package/dist/ui.cjs +635 -254
- package/dist/ui.d.cts +3 -2
- package/dist/ui.d.ts +3 -2
- package/dist/ui.js +9 -8
- package/dist/widgets.cjs +22 -14
- package/dist/widgets.js +7 -7
- package/package.json +8 -5
package/dist/extras.cjs
CHANGED
|
@@ -1077,7 +1077,7 @@ function forEachSubscriber(signal2, visit) {
|
|
|
1077
1077
|
}
|
|
1078
1078
|
|
|
1079
1079
|
// src/reactivity/track.ts
|
|
1080
|
-
var _runtimeVersion = true ? "4.
|
|
1080
|
+
var _runtimeVersion = true ? "4.8.0" : "dev";
|
|
1081
1081
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
1082
1082
|
function resolveReactiveApi() {
|
|
1083
1083
|
const g2 = globalThis;
|
|
@@ -1133,6 +1133,14 @@ var getSubscriberCount2 = API.getSubscriberCount;
|
|
|
1133
1133
|
var getSubscriberDeps2 = API.getSubscriberDeps;
|
|
1134
1134
|
var forEachSubscriber2 = API.forEachSubscriber;
|
|
1135
1135
|
|
|
1136
|
+
// src/core/devtoolsHook.ts
|
|
1137
|
+
function emitDevtools(hook, event, payload) {
|
|
1138
|
+
try {
|
|
1139
|
+
hook.emit(event, payload);
|
|
1140
|
+
} catch {
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1136
1144
|
// src/core/signals/derived.ts
|
|
1137
1145
|
function derived(getter, options) {
|
|
1138
1146
|
devAssert(typeof getter === "function", "derived: argument must be a getter function.");
|
|
@@ -1159,17 +1167,17 @@ function derived(getter, options) {
|
|
|
1159
1167
|
cs._d = false;
|
|
1160
1168
|
cs._init = true;
|
|
1161
1169
|
};
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
try {
|
|
1170
|
+
try {
|
|
1171
|
+
track2(() => {
|
|
1165
1172
|
cs._v = getter();
|
|
1166
1173
|
cs._d = false;
|
|
1167
1174
|
cs._init = true;
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1175
|
+
}, markDirty);
|
|
1176
|
+
} catch (err) {
|
|
1177
|
+
disposed = true;
|
|
1178
|
+
cleanup2(markDirty);
|
|
1179
|
+
throw err;
|
|
1180
|
+
}
|
|
1173
1181
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1174
1182
|
const validate = () => {
|
|
1175
1183
|
if (!cs._d || disposed || pendingError !== void 0) return;
|
|
@@ -1188,7 +1196,7 @@ function derived(getter, options) {
|
|
|
1188
1196
|
if (disposed) cleanup2(markDirty);
|
|
1189
1197
|
}
|
|
1190
1198
|
if (hook && !disposed && !Object.is(oldValue, cs._v)) {
|
|
1191
|
-
hook
|
|
1199
|
+
emitDevtools(hook, "computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
1192
1200
|
}
|
|
1193
1201
|
};
|
|
1194
1202
|
cs._validate = validate;
|
|
@@ -1239,7 +1247,7 @@ function derived(getter, options) {
|
|
|
1239
1247
|
}
|
|
1240
1248
|
}
|
|
1241
1249
|
};
|
|
1242
|
-
if (hook) hook
|
|
1250
|
+
if (hook) emitDevtools(hook, "computed:create", { signal: cs, name: debugName, getter: computedGetter });
|
|
1243
1251
|
return computedGetter;
|
|
1244
1252
|
}
|
|
1245
1253
|
|
|
@@ -1412,12 +1420,17 @@ function effect(effectFn, options) {
|
|
|
1412
1420
|
try {
|
|
1413
1421
|
retrack2(ctx.bodyFn, ctx.subscriber);
|
|
1414
1422
|
if (ctx.rerunPending) drainReruns(ctx);
|
|
1423
|
+
} catch (err) {
|
|
1424
|
+
ctx.disposed = true;
|
|
1425
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
1426
|
+
cleanup2(ctx.subscriber);
|
|
1427
|
+
throw err;
|
|
1415
1428
|
} finally {
|
|
1416
1429
|
ctx.running = false;
|
|
1417
1430
|
ctx.rerunPending = false;
|
|
1418
1431
|
}
|
|
1419
1432
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1420
|
-
if (hook) hook
|
|
1433
|
+
if (hook) emitDevtools(hook, "effect:create", { effectFn });
|
|
1421
1434
|
return () => disposeEffect(ctx);
|
|
1422
1435
|
}
|
|
1423
1436
|
|
|
@@ -1504,7 +1517,7 @@ function signal(initial, options) {
|
|
|
1504
1517
|
state2.__v++;
|
|
1505
1518
|
if (DEV) {
|
|
1506
1519
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1507
|
-
if (hook) hook
|
|
1520
|
+
if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
1508
1521
|
}
|
|
1509
1522
|
if (!enqueueBatchedSignal(state2)) {
|
|
1510
1523
|
notifySubscribers2(state2);
|
|
@@ -1518,7 +1531,7 @@ function signal(initial, options) {
|
|
|
1518
1531
|
state2.value = newValue;
|
|
1519
1532
|
state2.__v++;
|
|
1520
1533
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1521
|
-
if (hook) hook
|
|
1534
|
+
if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
1522
1535
|
if (!enqueueBatchedSignal(state2)) {
|
|
1523
1536
|
notifySubscribers2(state2);
|
|
1524
1537
|
}
|
|
@@ -1537,7 +1550,7 @@ function signal(initial, options) {
|
|
|
1537
1550
|
}
|
|
1538
1551
|
if (DEV) {
|
|
1539
1552
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1540
|
-
if (hook) hook
|
|
1553
|
+
if (hook) emitDevtools(hook, "signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
1541
1554
|
}
|
|
1542
1555
|
return [get, set];
|
|
1543
1556
|
}
|
|
@@ -1659,7 +1672,87 @@ function waitForRetryDelay(delay, signal2) {
|
|
|
1659
1672
|
});
|
|
1660
1673
|
}
|
|
1661
1674
|
|
|
1675
|
+
// src/data/structuralSharing.ts
|
|
1676
|
+
function isPlainObject(value) {
|
|
1677
|
+
if (value === null || typeof value !== "object") return false;
|
|
1678
|
+
const proto = Object.getPrototypeOf(value);
|
|
1679
|
+
return proto === Object.prototype || proto === null;
|
|
1680
|
+
}
|
|
1681
|
+
function isPlainArray(value) {
|
|
1682
|
+
return Array.isArray(value) && Object.getPrototypeOf(value) === Array.prototype;
|
|
1683
|
+
}
|
|
1684
|
+
function reconcile(prev, next, depth, walk, newRoot) {
|
|
1685
|
+
if (Object.is(prev, next)) return prev;
|
|
1686
|
+
const arrays = isPlainArray(prev) && isPlainArray(next);
|
|
1687
|
+
if (!arrays && !(isPlainObject(prev) && isPlainObject(next))) return next;
|
|
1688
|
+
if (Object.getPrototypeOf(prev) !== Object.getPrototypeOf(next)) return next;
|
|
1689
|
+
const nextObject = next;
|
|
1690
|
+
const seenAt = walk.path.get(nextObject);
|
|
1691
|
+
if (seenAt !== void 0) {
|
|
1692
|
+
walk.cycleTo = Math.min(walk.cycleTo, seenAt);
|
|
1693
|
+
return next;
|
|
1694
|
+
}
|
|
1695
|
+
const prevRecord = prev;
|
|
1696
|
+
const nextRecord = next;
|
|
1697
|
+
const nextKeys = arrays ? Array.from({ length: next.length }, (_, i2) => i2) : Object.keys(nextRecord);
|
|
1698
|
+
const prevSize = arrays ? prev.length : Object.keys(prevRecord).length;
|
|
1699
|
+
const copy = arrays ? new Array(nextKeys.length) : Object.create(Object.getPrototypeOf(next));
|
|
1700
|
+
let allFromPrev = prevSize === nextKeys.length;
|
|
1701
|
+
let allFromNext = true;
|
|
1702
|
+
const outerCycleTo = walk.cycleTo;
|
|
1703
|
+
walk.cycleTo = Number.POSITIVE_INFINITY;
|
|
1704
|
+
walk.path.set(nextObject, depth);
|
|
1705
|
+
for (const key of nextKeys) {
|
|
1706
|
+
if (arrays && !Object.hasOwn(nextRecord, key)) {
|
|
1707
|
+
if (Object.hasOwn(prevRecord, key)) allFromPrev = false;
|
|
1708
|
+
continue;
|
|
1709
|
+
}
|
|
1710
|
+
const nextChild = nextRecord[key];
|
|
1711
|
+
const hasPrev = Object.hasOwn(prevRecord, key);
|
|
1712
|
+
const shared = hasPrev ? reconcile(prevRecord[key], nextChild, depth + 1, walk, false) : nextChild;
|
|
1713
|
+
if (key === "__proto__") {
|
|
1714
|
+
Object.defineProperty(copy, key, { value: shared, writable: true, enumerable: true, configurable: true });
|
|
1715
|
+
} else {
|
|
1716
|
+
copy[key] = shared;
|
|
1717
|
+
}
|
|
1718
|
+
if (!hasPrev || !Object.is(shared, prevRecord[key])) allFromPrev = false;
|
|
1719
|
+
if (!Object.is(shared, nextChild)) allFromNext = false;
|
|
1720
|
+
}
|
|
1721
|
+
walk.path.delete(nextObject);
|
|
1722
|
+
const reached = walk.cycleTo;
|
|
1723
|
+
walk.cycleTo = Math.min(outerCycleTo, reached < depth ? reached : Number.POSITIVE_INFINITY);
|
|
1724
|
+
if (reached <= depth) return next;
|
|
1725
|
+
if (allFromPrev && !newRoot) return prev;
|
|
1726
|
+
if (allFromNext) return next;
|
|
1727
|
+
return copy;
|
|
1728
|
+
}
|
|
1729
|
+
function applyStructuralSharing(option2, prev, next, explicit = false) {
|
|
1730
|
+
if (option2 === false || prev === void 0) return next;
|
|
1731
|
+
const forceNew = explicit && !Object.is(prev, next);
|
|
1732
|
+
if (typeof option2 === "function") {
|
|
1733
|
+
const shared = option2(prev, next);
|
|
1734
|
+
return forceNew && Object.is(shared, prev) ? next : shared;
|
|
1735
|
+
}
|
|
1736
|
+
return reconcile(prev, next, 0, { path: /* @__PURE__ */ new Map(), cycleTo: Number.POSITIVE_INFINITY }, forceNew);
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1662
1739
|
// src/data/query.ts
|
|
1740
|
+
function shareSafely(option2, prev, next, explicit) {
|
|
1741
|
+
const shared = untracked2(
|
|
1742
|
+
() => runSelect("query structuralSharing", () => applyStructuralSharing(option2, prev, next, explicit))
|
|
1743
|
+
);
|
|
1744
|
+
return shared.ok ? shared.value : next;
|
|
1745
|
+
}
|
|
1746
|
+
function sharedView(entry) {
|
|
1747
|
+
const raw = entry.data;
|
|
1748
|
+
if (raw === void 0) return void 0;
|
|
1749
|
+
if (entry.hasShared && Object.is(entry.sharedFrom, raw)) return entry.shared;
|
|
1750
|
+
const value = shareSafely(true, entry.hasShared ? entry.shared : void 0, raw, entry.explicit);
|
|
1751
|
+
entry.shared = value;
|
|
1752
|
+
entry.sharedFrom = raw;
|
|
1753
|
+
entry.hasShared = true;
|
|
1754
|
+
return value;
|
|
1755
|
+
}
|
|
1663
1756
|
var globalQueryCache = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.query.cache.v1"), () => /* @__PURE__ */ new Map());
|
|
1664
1757
|
function getActiveQueryCache() {
|
|
1665
1758
|
return getRequestScopedCache("query") ?? globalQueryCache;
|
|
@@ -1685,7 +1778,11 @@ function getOrCreateEntry(cache, key, initialData) {
|
|
|
1685
1778
|
listeners: /* @__PURE__ */ new Set(),
|
|
1686
1779
|
refetchers: /* @__PURE__ */ new Set(),
|
|
1687
1780
|
controller: null,
|
|
1688
|
-
generation: 0
|
|
1781
|
+
generation: 0,
|
|
1782
|
+
explicit: false,
|
|
1783
|
+
shared: void 0,
|
|
1784
|
+
sharedFrom: void 0,
|
|
1785
|
+
hasShared: false
|
|
1689
1786
|
};
|
|
1690
1787
|
cache.set(key, entry);
|
|
1691
1788
|
}
|
|
@@ -1704,13 +1801,24 @@ function query(key, fetcher, options = {}) {
|
|
|
1704
1801
|
onSuccess,
|
|
1705
1802
|
onError,
|
|
1706
1803
|
onSettled,
|
|
1707
|
-
select: select3
|
|
1804
|
+
select: select3,
|
|
1805
|
+
structuralSharing = true
|
|
1708
1806
|
} = options;
|
|
1709
1807
|
const resolveKey = typeof key === "function" ? key : () => key;
|
|
1710
1808
|
const cache = getActiveQueryCache();
|
|
1711
1809
|
const [data2, setData] = signal(initialData);
|
|
1712
1810
|
const [isFetching, setIsFetching] = signal(false);
|
|
1713
1811
|
const [error, setError] = signal(void 0);
|
|
1812
|
+
const [updatedAt, setUpdatedAt] = signal(0);
|
|
1813
|
+
const [base2, setBase] = signal(void 0);
|
|
1814
|
+
let baseEntry = null;
|
|
1815
|
+
let baseValue;
|
|
1816
|
+
let baseExplicit = false;
|
|
1817
|
+
let customEntry = null;
|
|
1818
|
+
let customFrom;
|
|
1819
|
+
let customValue;
|
|
1820
|
+
let selectedEntry = null;
|
|
1821
|
+
let selectedValue;
|
|
1714
1822
|
let disposed = false;
|
|
1715
1823
|
let currentKey = null;
|
|
1716
1824
|
let attachedEntry = null;
|
|
@@ -1719,11 +1827,57 @@ function query(key, fetcher, options = {}) {
|
|
|
1719
1827
|
const loading = derived(() => isFetching() && data2() === void 0);
|
|
1720
1828
|
const isStale = derived(() => {
|
|
1721
1829
|
data2();
|
|
1830
|
+
updatedAt();
|
|
1722
1831
|
if (!currentKey) return true;
|
|
1723
1832
|
const entry = cache.get(currentKey);
|
|
1724
1833
|
if (!entry || entry.dataUpdatedAt === 0) return true;
|
|
1725
1834
|
return Date.now() - entry.dataUpdatedAt >= staleTime;
|
|
1726
1835
|
});
|
|
1836
|
+
function viewOf(entry) {
|
|
1837
|
+
const raw = entry.data;
|
|
1838
|
+
if (raw === void 0) return void 0;
|
|
1839
|
+
if (structuralSharing === false) return raw;
|
|
1840
|
+
if (typeof structuralSharing !== "function") return sharedView(entry);
|
|
1841
|
+
const sameEntry = customEntry === entry;
|
|
1842
|
+
if (sameEntry && Object.is(customFrom, raw)) return customValue;
|
|
1843
|
+
const value = shareSafely(structuralSharing, sameEntry ? customValue : void 0, raw, entry.explicit);
|
|
1844
|
+
customEntry = entry;
|
|
1845
|
+
customFrom = raw;
|
|
1846
|
+
customValue = value;
|
|
1847
|
+
return value;
|
|
1848
|
+
}
|
|
1849
|
+
function commitBase(entry, value) {
|
|
1850
|
+
const changed = !Object.is(value, baseValue);
|
|
1851
|
+
baseEntry = entry;
|
|
1852
|
+
baseValue = value;
|
|
1853
|
+
if (!select3) {
|
|
1854
|
+
setData(value);
|
|
1855
|
+
return;
|
|
1856
|
+
}
|
|
1857
|
+
if (!changed) return;
|
|
1858
|
+
baseExplicit = entry?.explicit === true;
|
|
1859
|
+
setBase(value);
|
|
1860
|
+
}
|
|
1861
|
+
const stopSelect = select3 ? effect(() => {
|
|
1862
|
+
const raw = base2();
|
|
1863
|
+
const entry = baseEntry;
|
|
1864
|
+
const explicit = baseExplicit;
|
|
1865
|
+
baseExplicit = false;
|
|
1866
|
+
if (entry === null && selectedEntry === null) return;
|
|
1867
|
+
if (raw === void 0) {
|
|
1868
|
+
selectedEntry = entry;
|
|
1869
|
+
selectedValue = void 0;
|
|
1870
|
+
setData(void 0);
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
const selected = runSelect("query select", () => select3(raw));
|
|
1874
|
+
if (!selected.ok) return;
|
|
1875
|
+
const prev = selectedEntry === entry ? selectedValue : void 0;
|
|
1876
|
+
const value = shareSafely(structuralSharing, prev, selected.value, explicit);
|
|
1877
|
+
selectedEntry = entry;
|
|
1878
|
+
selectedValue = value;
|
|
1879
|
+
setData(value);
|
|
1880
|
+
}) : null;
|
|
1727
1881
|
function detachFromEntry() {
|
|
1728
1882
|
const entry = attachedEntry;
|
|
1729
1883
|
const key2 = attachedKey;
|
|
@@ -1782,7 +1936,7 @@ function query(key, fetcher, options = {}) {
|
|
|
1782
1936
|
const settledError = entry.error;
|
|
1783
1937
|
runCallback("query onError", () => onError?.(settledError));
|
|
1784
1938
|
} else if (entry.data !== void 0) {
|
|
1785
|
-
const settledData = entry
|
|
1939
|
+
const settledData = viewOf(entry);
|
|
1786
1940
|
runCallback("query onSuccess", () => onSuccess?.(settledData));
|
|
1787
1941
|
}
|
|
1788
1942
|
runCallback("query onSettled", () => onSettled?.());
|
|
@@ -1813,17 +1967,14 @@ function query(key, fetcher, options = {}) {
|
|
|
1813
1967
|
entry.promise = null;
|
|
1814
1968
|
entry.controller = null;
|
|
1815
1969
|
entry.data = result;
|
|
1970
|
+
entry.explicit = false;
|
|
1816
1971
|
entry.dataUpdatedAt = Date.now();
|
|
1817
1972
|
entry.error = void 0;
|
|
1818
1973
|
notifyListeners(entry.listeners, "query cache listener");
|
|
1819
1974
|
if (disposed || currentKey !== key2) return;
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
setIsFetching(false);
|
|
1824
|
-
setError(void 0);
|
|
1825
|
-
});
|
|
1826
|
-
runCallback("query onSuccess", () => onSuccess?.(result));
|
|
1975
|
+
if (!entry.listeners.has(onCacheUpdate)) onCacheUpdate();
|
|
1976
|
+
const committedResult = viewOf(entry);
|
|
1977
|
+
runCallback("query onSuccess", () => onSuccess?.(committedResult));
|
|
1827
1978
|
} catch (err) {
|
|
1828
1979
|
if (entry.generation !== generation) return;
|
|
1829
1980
|
entry.promise = null;
|
|
@@ -1853,18 +2004,19 @@ function query(key, fetcher, options = {}) {
|
|
|
1853
2004
|
const entry = cache.get(currentKey);
|
|
1854
2005
|
if (!entry) {
|
|
1855
2006
|
batch(() => {
|
|
1856
|
-
|
|
2007
|
+
commitBase(null, void 0);
|
|
1857
2008
|
setError(void 0);
|
|
1858
2009
|
setIsFetching(false);
|
|
2010
|
+
setUpdatedAt(0);
|
|
1859
2011
|
});
|
|
1860
2012
|
return;
|
|
1861
2013
|
}
|
|
1862
|
-
const
|
|
1863
|
-
const selected = raw !== void 0 && select3 ? runSelect("query select", () => select3(raw)) : { ok: true, value: raw };
|
|
2014
|
+
const view = viewOf(entry);
|
|
1864
2015
|
batch(() => {
|
|
1865
|
-
|
|
2016
|
+
commitBase(entry, view);
|
|
1866
2017
|
setError(entry.error);
|
|
1867
2018
|
if (!entry.promise) setIsFetching(false);
|
|
2019
|
+
setUpdatedAt(entry.dataUpdatedAt);
|
|
1868
2020
|
});
|
|
1869
2021
|
}
|
|
1870
2022
|
const effectCleanup = effect(() => {
|
|
@@ -1874,11 +2026,11 @@ function query(key, fetcher, options = {}) {
|
|
|
1874
2026
|
const entry = getOrCreateEntry(cache, key2, initialData);
|
|
1875
2027
|
attachToEntry(entry, key2);
|
|
1876
2028
|
if (entry.data !== void 0) {
|
|
1877
|
-
const
|
|
1878
|
-
const selected = runSelect("query select", () => select3 ? select3(raw) : raw);
|
|
2029
|
+
const view = viewOf(entry);
|
|
1879
2030
|
batch(() => {
|
|
1880
|
-
|
|
2031
|
+
commitBase(entry, view);
|
|
1881
2032
|
setError(entry.error);
|
|
2033
|
+
setUpdatedAt(entry.dataUpdatedAt);
|
|
1882
2034
|
});
|
|
1883
2035
|
}
|
|
1884
2036
|
if (!keyChanged && currentKey === key2 && entry.data !== void 0) {
|
|
@@ -1916,6 +2068,7 @@ function query(key, fetcher, options = {}) {
|
|
|
1916
2068
|
if (disposed) return;
|
|
1917
2069
|
disposed = true;
|
|
1918
2070
|
effectCleanup();
|
|
2071
|
+
stopSelect?.();
|
|
1919
2072
|
loading.dispose();
|
|
1920
2073
|
isStale.dispose();
|
|
1921
2074
|
if (intervalTimer) clearInterval(intervalTimer);
|
|
@@ -1947,13 +2100,15 @@ function invalidateQueries(keyOrPredicate) {
|
|
|
1947
2100
|
}
|
|
1948
2101
|
}
|
|
1949
2102
|
function getQueryData(key) {
|
|
1950
|
-
|
|
2103
|
+
const entry = getActiveQueryCache().get(key);
|
|
2104
|
+
return entry ? sharedView(entry) : void 0;
|
|
1951
2105
|
}
|
|
1952
2106
|
function setQueryData(key, data2) {
|
|
1953
2107
|
const entry = getActiveQueryCache().get(key);
|
|
1954
2108
|
if (!entry) return;
|
|
1955
|
-
const newData = typeof data2 === "function" ? data2(entry
|
|
2109
|
+
const newData = typeof data2 === "function" ? data2(sharedView(entry)) : data2;
|
|
1956
2110
|
entry.data = newData;
|
|
2111
|
+
entry.explicit = true;
|
|
1957
2112
|
entry.dataUpdatedAt = Date.now();
|
|
1958
2113
|
notifyListeners(entry.listeners, "query cache listener");
|
|
1959
2114
|
}
|
|
@@ -2337,6 +2492,15 @@ function resource(sourceOrFetcher, fetcherOrOptions, maybeOptions) {
|
|
|
2337
2492
|
const [loading, setLoading] = signal(false);
|
|
2338
2493
|
const [error, setError] = signal(void 0);
|
|
2339
2494
|
let currentData = options.initialValue;
|
|
2495
|
+
function commitData(next, explicit) {
|
|
2496
|
+
const sharing = options.structuralSharing ?? true;
|
|
2497
|
+
const shared = untracked2(
|
|
2498
|
+
() => runSelect("resource structuralSharing", () => applyStructuralSharing(sharing, currentData, next, explicit))
|
|
2499
|
+
);
|
|
2500
|
+
currentData = shared.ok ? shared.value : next;
|
|
2501
|
+
setData(currentData);
|
|
2502
|
+
return currentData;
|
|
2503
|
+
}
|
|
2340
2504
|
let abortController = null;
|
|
2341
2505
|
let disposed = false;
|
|
2342
2506
|
let effectCleanup = null;
|
|
@@ -2356,12 +2520,12 @@ function resource(sourceOrFetcher, fetcherOrOptions, maybeOptions) {
|
|
|
2356
2520
|
try {
|
|
2357
2521
|
const result = await withRetry(() => fetcher(sourceValue, { signal: signal2, prev }), options.retry, void 0, signal2);
|
|
2358
2522
|
if (version !== fetchVersion || disposed) return;
|
|
2359
|
-
|
|
2523
|
+
let committed = result;
|
|
2360
2524
|
batch(() => {
|
|
2361
|
-
|
|
2525
|
+
committed = commitData(result, false);
|
|
2362
2526
|
setLoading(false);
|
|
2363
2527
|
});
|
|
2364
|
-
runCallback("resource onSuccess", () => options.onSuccess?.(
|
|
2528
|
+
runCallback("resource onSuccess", () => options.onSuccess?.(committed));
|
|
2365
2529
|
} catch (err) {
|
|
2366
2530
|
if (version !== fetchVersion || disposed) return;
|
|
2367
2531
|
if (isAbortError(err)) {
|
|
@@ -2395,8 +2559,7 @@ function resource(sourceOrFetcher, fetcherOrOptions, maybeOptions) {
|
|
|
2395
2559
|
refetch: () => doFetch(source2 ? source2() : void 0),
|
|
2396
2560
|
mutate: (value) => {
|
|
2397
2561
|
const newValue = typeof value === "function" ? value(currentData) : value;
|
|
2398
|
-
|
|
2399
|
-
setData(newValue);
|
|
2562
|
+
commitData(newValue, true);
|
|
2400
2563
|
},
|
|
2401
2564
|
abort: () => abortController?.abort(),
|
|
2402
2565
|
dispose: () => {
|
|
@@ -2916,8 +3079,10 @@ function socket(url, options) {
|
|
|
2916
3079
|
function stripControlChars(value) {
|
|
2917
3080
|
return value.replace(/[\x00-\x20\x7f-\x9f]+/g, "");
|
|
2918
3081
|
}
|
|
3082
|
+
var ASCII_UPPER = /[A-Z]/;
|
|
3083
|
+
var ASCII_UPPER_G = /[A-Z]/g;
|
|
2919
3084
|
function canonicalAttrName(name) {
|
|
2920
|
-
return name.replace(
|
|
3085
|
+
return ASCII_UPPER.test(name) ? name.replace(ASCII_UPPER_G, (ch) => String.fromCharCode(ch.charCodeAt(0) + 32)) : name;
|
|
2921
3086
|
}
|
|
2922
3087
|
function isEventHandlerAttr(name) {
|
|
2923
3088
|
if (name.length < 3) return false;
|
|
@@ -2930,6 +3095,9 @@ function sanitizeUrl(url) {
|
|
|
2930
3095
|
const probe = stripControlChars(url).trim();
|
|
2931
3096
|
if (!probe) return "";
|
|
2932
3097
|
const output2 = url.replace(OUTER_TRIM, "");
|
|
3098
|
+
if (probe.length >= 2 && (probe[0] === "\\" || probe[0] === "/") && (probe[1] === "\\" || probe[1] === "/") && (probe[0] === "\\" || probe[1] === "\\")) {
|
|
3099
|
+
return "";
|
|
3100
|
+
}
|
|
2933
3101
|
const lower = probe.toLowerCase();
|
|
2934
3102
|
let schemeEnd = -1;
|
|
2935
3103
|
for (let i2 = 0; i2 < lower.length; i2++) {
|
|
@@ -2946,19 +3114,58 @@ function sanitizeUrl(url) {
|
|
|
2946
3114
|
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
2947
3115
|
return output2;
|
|
2948
3116
|
}
|
|
2949
|
-
var SRCSET_DESCRIPTOR = /^\
|
|
3117
|
+
var SRCSET_DESCRIPTOR = /^\d+(\.\d+)?[wx]$/;
|
|
3118
|
+
function isSrcsetWhitespace(ch) {
|
|
3119
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
3120
|
+
}
|
|
2950
3121
|
function sanitizeSrcset(value) {
|
|
2951
|
-
const
|
|
3122
|
+
const input2 = String(value);
|
|
2952
3123
|
const out = [];
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
if (
|
|
2958
|
-
|
|
2959
|
-
|
|
3124
|
+
let i2 = 0;
|
|
3125
|
+
const n = input2.length;
|
|
3126
|
+
while (i2 < n) {
|
|
3127
|
+
while (i2 < n && (isSrcsetWhitespace(input2[i2]) || input2[i2] === ",")) i2++;
|
|
3128
|
+
if (i2 >= n) break;
|
|
3129
|
+
const urlStart = i2;
|
|
3130
|
+
while (i2 < n && !isSrcsetWhitespace(input2[i2])) i2++;
|
|
3131
|
+
let url = input2.slice(urlStart, i2);
|
|
3132
|
+
const descriptors = [];
|
|
3133
|
+
if (url.endsWith(",")) {
|
|
3134
|
+
url = url.replace(/,+$/, "");
|
|
3135
|
+
} else {
|
|
3136
|
+
let current = "";
|
|
3137
|
+
let inParens = false;
|
|
3138
|
+
while (i2 < n) {
|
|
3139
|
+
const ch = input2[i2];
|
|
3140
|
+
if (inParens) {
|
|
3141
|
+
current += ch;
|
|
3142
|
+
if (ch === ")") inParens = false;
|
|
3143
|
+
i2++;
|
|
3144
|
+
continue;
|
|
3145
|
+
}
|
|
3146
|
+
if (isSrcsetWhitespace(ch)) {
|
|
3147
|
+
if (current) descriptors.push(current);
|
|
3148
|
+
current = "";
|
|
3149
|
+
i2++;
|
|
3150
|
+
continue;
|
|
3151
|
+
}
|
|
3152
|
+
if (ch === ",") {
|
|
3153
|
+
i2++;
|
|
3154
|
+
break;
|
|
3155
|
+
}
|
|
3156
|
+
if (ch === "(") inParens = true;
|
|
3157
|
+
current += ch;
|
|
3158
|
+
i2++;
|
|
3159
|
+
}
|
|
3160
|
+
if (current) descriptors.push(current);
|
|
3161
|
+
}
|
|
3162
|
+
if (url === "") continue;
|
|
3163
|
+
if (descriptors.length > 1) continue;
|
|
3164
|
+
if (descriptors.length === 1 && !SRCSET_DESCRIPTOR.test(descriptors[0])) continue;
|
|
3165
|
+
const safe = sanitizeUrl(url);
|
|
2960
3166
|
if (!safe) continue;
|
|
2961
|
-
|
|
3167
|
+
if (safe.startsWith(",") || safe.endsWith(",")) continue;
|
|
3168
|
+
out.push(descriptors.length === 1 ? `${safe} ${descriptors[0]}` : safe);
|
|
2962
3169
|
}
|
|
2963
3170
|
return out.join(", ");
|
|
2964
3171
|
}
|
|
@@ -3017,8 +3224,16 @@ var BLOCKED_CSS_NEEDLES = [
|
|
|
3017
3224
|
"behavior:",
|
|
3018
3225
|
"@import",
|
|
3019
3226
|
"image-set(",
|
|
3020
|
-
"filter:progid"
|
|
3227
|
+
"filter:progid",
|
|
3228
|
+
// CSS Images 4 `image("…")` and CSS Values 5 `src("…")` take a URL as a
|
|
3229
|
+
// plain STRING, so they fetch without ever spelling `url(`. Support is thin
|
|
3230
|
+
// today, which is exactly when a blocklist should get ahead of it.
|
|
3231
|
+
"image(",
|
|
3232
|
+
"src("
|
|
3021
3233
|
];
|
|
3234
|
+
var CSS_REASON_MOZ_BINDING = 4;
|
|
3235
|
+
var CSS_REASON_BEHAVIOR = 5;
|
|
3236
|
+
var CSS_REASON_PROGID = 8;
|
|
3022
3237
|
function describeElement(el) {
|
|
3023
3238
|
if (!el) return "an element";
|
|
3024
3239
|
let out = el.tagName.toLowerCase();
|
|
@@ -3042,7 +3257,9 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
3042
3257
|
"behavior: loads and runs a remote HTC script",
|
|
3043
3258
|
"@import pulls in a remote stylesheet",
|
|
3044
3259
|
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
3045
|
-
"filter:progid activates legacy scriptable filters"
|
|
3260
|
+
"filter:progid activates legacy scriptable filters",
|
|
3261
|
+
"image() fetches its string argument as a URL, the same exfiltration channel as url()",
|
|
3262
|
+
"src() fetches its string argument as a URL, the same exfiltration channel as url()"
|
|
3046
3263
|
];
|
|
3047
3264
|
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
3048
3265
|
const where = describeElement(ctx?.element);
|
|
@@ -3057,27 +3274,145 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
3057
3274
|
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.`;
|
|
3058
3275
|
});
|
|
3059
3276
|
}
|
|
3277
|
+
function normalizeCssForScan(value) {
|
|
3278
|
+
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
3279
|
+
return normalized.toLowerCase().replace(/\s+/g, "");
|
|
3280
|
+
}
|
|
3060
3281
|
function blockedCssReason(value) {
|
|
3061
3282
|
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
3062
|
-
const
|
|
3063
|
-
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
3283
|
+
const lower = normalizeCssForScan(value);
|
|
3064
3284
|
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
3065
3285
|
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
3066
3286
|
}
|
|
3067
3287
|
return -1;
|
|
3068
3288
|
}
|
|
3069
|
-
|
|
3070
|
-
|
|
3289
|
+
var STYLESHEET_BLOCKED_FUNCTIONS = ["url", "image-set", "image", "src", "expression"];
|
|
3290
|
+
function stripCssFunctions(css) {
|
|
3291
|
+
const pattern2 = new RegExp(`(?:-webkit-)?(${STYLESHEET_BLOCKED_FUNCTIONS.join("|")})\\s*\\(`, "gi");
|
|
3292
|
+
let out = "";
|
|
3293
|
+
let last = 0;
|
|
3294
|
+
for (let match = pattern2.exec(css); match !== null; match = pattern2.exec(css)) {
|
|
3295
|
+
const before = match.index > 0 ? css[match.index - 1] : "";
|
|
3296
|
+
if (/[\w-]/.test(before)) continue;
|
|
3297
|
+
let depth = 1;
|
|
3298
|
+
let i2 = pattern2.lastIndex;
|
|
3299
|
+
let quote2 = "";
|
|
3300
|
+
for (; i2 < css.length && depth > 0; i2++) {
|
|
3301
|
+
const ch = css[i2];
|
|
3302
|
+
if (quote2) {
|
|
3303
|
+
if (ch === "\\") i2++;
|
|
3304
|
+
else if (ch === quote2) quote2 = "";
|
|
3305
|
+
} else if (ch === '"' || ch === "'") quote2 = ch;
|
|
3306
|
+
else if (ch === "(") depth++;
|
|
3307
|
+
else if (ch === ")") depth--;
|
|
3308
|
+
}
|
|
3309
|
+
out += `${css.slice(last, match.index)}/* ${match[1].toLowerCase()}() removed */`;
|
|
3310
|
+
last = i2;
|
|
3311
|
+
pattern2.lastIndex = i2;
|
|
3312
|
+
}
|
|
3313
|
+
return out + css.slice(last);
|
|
3314
|
+
}
|
|
3315
|
+
function sanitizeStylesheetText(css) {
|
|
3316
|
+
let text2 = css.includes("\\") ? decodeCssEscapes(css) : css;
|
|
3317
|
+
text2 = text2.replace(/@import\b[^;{}]*;?/gi, "/* @import removed */");
|
|
3318
|
+
text2 = stripCssFunctions(text2);
|
|
3319
|
+
text2 = text2.replace(/(^|[;{\s])behavior\s*:[^;}]*;?/gi, "$1/* behavior removed */");
|
|
3320
|
+
text2 = text2.replace(/(^|[;{\s])-moz-binding\s*:[^;}]*;?/gi, "$1/* -moz-binding removed */");
|
|
3321
|
+
text2 = text2.replace(/(^|[;{\s])(-ms-)?filter\s*:[^;}]*progid[^;}]*;?/gi, "$1/* filter:progid removed */");
|
|
3322
|
+
return text2;
|
|
3323
|
+
}
|
|
3324
|
+
function sanitizeCSSDeclaration(property, value, context) {
|
|
3325
|
+
const reason = blockedDeclarationReason(property, value);
|
|
3071
3326
|
if (reason === -1) return value;
|
|
3072
|
-
warnDroppedDeclaration(value, reason, context);
|
|
3327
|
+
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
3073
3328
|
return "";
|
|
3074
3329
|
}
|
|
3330
|
+
function blockedDeclarationReason(property, value) {
|
|
3331
|
+
const reason = blockedCssReason(value);
|
|
3332
|
+
if (reason !== -1) return reason;
|
|
3333
|
+
const name = canonicalAttrName(property);
|
|
3334
|
+
if (name === "behavior") return CSS_REASON_BEHAVIOR;
|
|
3335
|
+
if (name === "-moz-binding") return CSS_REASON_MOZ_BINDING;
|
|
3336
|
+
if ((name === "filter" || name === "-ms-filter") && normalizeCssForScan(value).includes("progid:")) {
|
|
3337
|
+
return CSS_REASON_PROGID;
|
|
3338
|
+
}
|
|
3339
|
+
return -1;
|
|
3340
|
+
}
|
|
3341
|
+
function parseStyleDeclarations(css) {
|
|
3342
|
+
const chunks = [];
|
|
3343
|
+
let buf = "";
|
|
3344
|
+
let depth = 0;
|
|
3345
|
+
let quote2 = "";
|
|
3346
|
+
for (let i2 = 0; i2 < css.length; i2++) {
|
|
3347
|
+
const ch = css[i2];
|
|
3348
|
+
if (quote2) {
|
|
3349
|
+
buf += ch;
|
|
3350
|
+
if (ch === "\\" && i2 + 1 < css.length) buf += css[++i2];
|
|
3351
|
+
else if (ch === quote2) quote2 = "";
|
|
3352
|
+
continue;
|
|
3353
|
+
}
|
|
3354
|
+
if (ch === "\\") {
|
|
3355
|
+
buf += ch;
|
|
3356
|
+
if (i2 + 1 < css.length) buf += css[++i2];
|
|
3357
|
+
continue;
|
|
3358
|
+
}
|
|
3359
|
+
if (ch === "/" && css[i2 + 1] === "*") {
|
|
3360
|
+
const end = css.indexOf("*/", i2 + 2);
|
|
3361
|
+
if (end === -1) return null;
|
|
3362
|
+
i2 = end + 1;
|
|
3363
|
+
continue;
|
|
3364
|
+
}
|
|
3365
|
+
if (ch === '"' || ch === "'") quote2 = ch;
|
|
3366
|
+
else if (ch === "(" || ch === "[") depth++;
|
|
3367
|
+
else if (ch === ")" || ch === "]") {
|
|
3368
|
+
if (--depth < 0) return null;
|
|
3369
|
+
} else if (ch === "{" || ch === "}") return null;
|
|
3370
|
+
else if (ch === ";" && depth === 0) {
|
|
3371
|
+
chunks.push(buf);
|
|
3372
|
+
buf = "";
|
|
3373
|
+
continue;
|
|
3374
|
+
}
|
|
3375
|
+
buf += ch;
|
|
3376
|
+
}
|
|
3377
|
+
if (quote2 || depth !== 0) return null;
|
|
3378
|
+
chunks.push(buf);
|
|
3379
|
+
const out = [];
|
|
3380
|
+
for (const chunk of chunks) {
|
|
3381
|
+
const colon = chunk.indexOf(":");
|
|
3382
|
+
if (colon === -1) continue;
|
|
3383
|
+
const rawName = chunk.slice(0, colon).trim();
|
|
3384
|
+
if (!/^(--[\w-]+|-?[a-zA-Z_][\w-]*)$/.test(rawName)) continue;
|
|
3385
|
+
let value = chunk.slice(colon + 1).trim();
|
|
3386
|
+
const bang = /!\s*important\s*$/i.exec(value);
|
|
3387
|
+
if (bang) value = value.slice(0, bang.index).trim();
|
|
3388
|
+
if (value === "") continue;
|
|
3389
|
+
const property = rawName.startsWith("--") ? rawName : canonicalAttrName(rawName);
|
|
3390
|
+
out.push([property, value, bang !== null]);
|
|
3391
|
+
}
|
|
3392
|
+
return out;
|
|
3393
|
+
}
|
|
3394
|
+
function sanitizeStyleDeclarationList(cssText, context) {
|
|
3395
|
+
const input2 = String(cssText);
|
|
3396
|
+
const declarations = parseStyleDeclarations(input2);
|
|
3397
|
+
if (declarations === null) {
|
|
3398
|
+
if (blockedCssReason(input2) !== -1) warnDroppedDeclaration(input2, blockedCssReason(input2), context);
|
|
3399
|
+
return "";
|
|
3400
|
+
}
|
|
3401
|
+
const kept = [];
|
|
3402
|
+
for (const [property, value, important] of declarations) {
|
|
3403
|
+
const reason = blockedDeclarationReason(property, value);
|
|
3404
|
+
if (reason !== -1) {
|
|
3405
|
+
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
3406
|
+
continue;
|
|
3407
|
+
}
|
|
3408
|
+
kept.push(`${property}: ${value}${important ? " !important" : ""}`);
|
|
3409
|
+
}
|
|
3410
|
+
return kept.join("; ");
|
|
3411
|
+
}
|
|
3075
3412
|
function sanitizeStyleAttribute(cssText, context) {
|
|
3076
3413
|
const input2 = String(cssText);
|
|
3077
3414
|
if (input2.trim() === "") return "";
|
|
3078
|
-
if (typeof document === "undefined")
|
|
3079
|
-
return sanitizeCSSValue(input2, context) === "" ? "" : input2;
|
|
3080
|
-
}
|
|
3415
|
+
if (typeof document === "undefined") return sanitizeStyleDeclarationList(input2, context);
|
|
3081
3416
|
const probe = document.createElement("div");
|
|
3082
3417
|
try {
|
|
3083
3418
|
probe.style.cssText = input2;
|
|
@@ -3088,8 +3423,7 @@ function sanitizeStyleAttribute(cssText, context) {
|
|
|
3088
3423
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
3089
3424
|
const property = probe.style[i2];
|
|
3090
3425
|
const value = probe.style.getPropertyValue(property);
|
|
3091
|
-
|
|
3092
|
-
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
3426
|
+
const reason = blockedDeclarationReason(property, value);
|
|
3093
3427
|
if (reason !== -1) {
|
|
3094
3428
|
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
3095
3429
|
continue;
|
|
@@ -3137,6 +3471,9 @@ var HTML_CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set(["srcdoc"]);
|
|
|
3137
3471
|
function isHtmlContentAttribute(name) {
|
|
3138
3472
|
return HTML_CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
3139
3473
|
}
|
|
3474
|
+
function isUrlAttribute(attr) {
|
|
3475
|
+
return URL_ATTRIBUTES.has(attr.toLowerCase());
|
|
3476
|
+
}
|
|
3140
3477
|
function isPolicyAttribute(name) {
|
|
3141
3478
|
const lower = name.toLowerCase();
|
|
3142
3479
|
return lower === "style" || URL_ATTRIBUTES.has(lower);
|
|
@@ -3148,6 +3485,11 @@ function sanitizeAttributeString(attr, value, context) {
|
|
|
3148
3485
|
if (lower === "style") return sanitizeStyleAttribute(value, context);
|
|
3149
3486
|
return value;
|
|
3150
3487
|
}
|
|
3488
|
+
function resolveAttributeValue(attr, value, context) {
|
|
3489
|
+
if (!isPolicyAttribute(attr)) return value;
|
|
3490
|
+
const safe = sanitizeAttributeString(attr, value, context);
|
|
3491
|
+
return safe === "" ? null : safe;
|
|
3492
|
+
}
|
|
3151
3493
|
|
|
3152
3494
|
// src/ui/stream.ts
|
|
3153
3495
|
function validateSseUrl(raw) {
|
|
@@ -3571,6 +3913,13 @@ var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototyp
|
|
|
3571
3913
|
function isUnsafeKey(key) {
|
|
3572
3914
|
return UNSAFE_KEYS.has(key);
|
|
3573
3915
|
}
|
|
3916
|
+
function readOwnGlobal(key) {
|
|
3917
|
+
if (typeof window === "undefined") return void 0;
|
|
3918
|
+
if (!Object.hasOwn(window, key)) return void 0;
|
|
3919
|
+
const value = window[key];
|
|
3920
|
+
if (typeof Node !== "undefined" && value instanceof Node) return void 0;
|
|
3921
|
+
return value;
|
|
3922
|
+
}
|
|
3574
3923
|
function stripUnsafeKeys(obj) {
|
|
3575
3924
|
const out = {};
|
|
3576
3925
|
for (const k of Object.keys(obj)) {
|
|
@@ -3888,13 +4237,19 @@ function colorScheme() {
|
|
|
3888
4237
|
}
|
|
3889
4238
|
|
|
3890
4239
|
// src/browser/format.ts
|
|
4240
|
+
var I18N_STATE = /* @__PURE__ */ Symbol.for("sibujs.i18n.v1");
|
|
4241
|
+
function activeI18nLocale() {
|
|
4242
|
+
const state2 = globalThis[I18N_STATE];
|
|
4243
|
+
if (!state2) return void 0;
|
|
4244
|
+
return state2.getLocale ? state2.getLocale() : state2.locale?.[0]();
|
|
4245
|
+
}
|
|
3891
4246
|
function formatNumber(value, options) {
|
|
3892
4247
|
const { locale, ...formatOptions } = options ?? {};
|
|
3893
|
-
return new Intl.NumberFormat(locale, formatOptions).format(value);
|
|
4248
|
+
return new Intl.NumberFormat(locale ?? activeI18nLocale(), formatOptions).format(value);
|
|
3894
4249
|
}
|
|
3895
4250
|
function formatCurrency(value, currency, options) {
|
|
3896
4251
|
const { locale, ...formatOptions } = options ?? {};
|
|
3897
|
-
return new Intl.NumberFormat(locale, {
|
|
4252
|
+
return new Intl.NumberFormat(locale ?? activeI18nLocale(), {
|
|
3898
4253
|
...formatOptions,
|
|
3899
4254
|
style: "currency",
|
|
3900
4255
|
currency
|
|
@@ -4863,6 +5218,11 @@ function imageLoader(src) {
|
|
|
4863
5218
|
abandonCurrent();
|
|
4864
5219
|
resetState();
|
|
4865
5220
|
if (disposed || token !== startToken) return;
|
|
5221
|
+
const safe = sanitizeUrl(String(url));
|
|
5222
|
+
if (!safe) {
|
|
5223
|
+
setStatus("error");
|
|
5224
|
+
return;
|
|
5225
|
+
}
|
|
4866
5226
|
const img2 = new Image();
|
|
4867
5227
|
current = img2;
|
|
4868
5228
|
currentSettled = false;
|
|
@@ -4881,7 +5241,7 @@ function imageLoader(src) {
|
|
|
4881
5241
|
currentSettled = true;
|
|
4882
5242
|
setStatus("error");
|
|
4883
5243
|
};
|
|
4884
|
-
img2.src =
|
|
5244
|
+
img2.src = safe;
|
|
4885
5245
|
}
|
|
4886
5246
|
let srcEffectTeardown = null;
|
|
4887
5247
|
if (typeof src === "function") {
|
|
@@ -4907,6 +5267,9 @@ function imageLoader(src) {
|
|
|
4907
5267
|
}
|
|
4908
5268
|
|
|
4909
5269
|
// src/patterns/machine.ts
|
|
5270
|
+
function ownEntry(table2, key) {
|
|
5271
|
+
return Object.hasOwn(table2, key) ? table2[key] : void 0;
|
|
5272
|
+
}
|
|
4910
5273
|
function machine(config) {
|
|
4911
5274
|
const [state2, setState] = signal(config.initial);
|
|
4912
5275
|
const [context, setContext] = signal(config.context || {});
|
|
@@ -4928,9 +5291,9 @@ function machine(config) {
|
|
|
4928
5291
|
}
|
|
4929
5292
|
}
|
|
4930
5293
|
function step(event) {
|
|
4931
|
-
const stateDef = config.states
|
|
5294
|
+
const stateDef = ownEntry(config.states, currentState);
|
|
4932
5295
|
if (!stateDef?.on) return;
|
|
4933
|
-
const transition2 = stateDef.on
|
|
5296
|
+
const transition2 = ownEntry(stateDef.on, event);
|
|
4934
5297
|
if (!transition2) return;
|
|
4935
5298
|
let target;
|
|
4936
5299
|
let guard;
|
|
@@ -4958,7 +5321,7 @@ function machine(config) {
|
|
|
4958
5321
|
if (action) setContext(nextContext);
|
|
4959
5322
|
setState(target);
|
|
4960
5323
|
});
|
|
4961
|
-
const targetDef = config.states
|
|
5324
|
+
const targetDef = ownEntry(config.states, target);
|
|
4962
5325
|
if (targetDef?.entry) {
|
|
4963
5326
|
targetDef.entry(currentContext);
|
|
4964
5327
|
}
|
|
@@ -4968,7 +5331,7 @@ function machine(config) {
|
|
|
4968
5331
|
if (processing) return;
|
|
4969
5332
|
drain();
|
|
4970
5333
|
}
|
|
4971
|
-
const initialDef = config.states
|
|
5334
|
+
const initialDef = ownEntry(config.states, config.initial);
|
|
4972
5335
|
if (initialDef?.entry) {
|
|
4973
5336
|
processing = true;
|
|
4974
5337
|
try {
|
|
@@ -4986,9 +5349,9 @@ function machine(config) {
|
|
|
4986
5349
|
}
|
|
4987
5350
|
function can(event) {
|
|
4988
5351
|
const currentState2 = state2();
|
|
4989
|
-
const stateDef = config.states
|
|
5352
|
+
const stateDef = ownEntry(config.states, currentState2);
|
|
4990
5353
|
if (!stateDef?.on) return false;
|
|
4991
|
-
const transition2 = stateDef.on
|
|
5354
|
+
const transition2 = ownEntry(stateDef.on, event);
|
|
4992
5355
|
if (!transition2) return false;
|
|
4993
5356
|
if (typeof transition2 === "string") return true;
|
|
4994
5357
|
if (transition2.guard) {
|
|
@@ -7065,31 +7428,6 @@ function announce(message, priority = "polite") {
|
|
|
7065
7428
|
|
|
7066
7429
|
// src/ui/scopedStyle.ts
|
|
7067
7430
|
var _scope = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.scopedStyle.v1"), () => ({ n: 0 }));
|
|
7068
|
-
function decodeCssEscapes2(css) {
|
|
7069
|
-
return css.replace(/\\([0-9a-f]{1,6})[ \t\n\r\f]?|\\([^\n])/gi, (_match, hex, ch) => {
|
|
7070
|
-
if (hex) {
|
|
7071
|
-
const code2 = Number.parseInt(hex, 16);
|
|
7072
|
-
if (Number.isFinite(code2) && code2 > 0 && code2 <= 1114111) {
|
|
7073
|
-
try {
|
|
7074
|
-
return String.fromCodePoint(code2);
|
|
7075
|
-
} catch {
|
|
7076
|
-
return "";
|
|
7077
|
-
}
|
|
7078
|
-
}
|
|
7079
|
-
return "";
|
|
7080
|
-
}
|
|
7081
|
-
return ch || "";
|
|
7082
|
-
});
|
|
7083
|
-
}
|
|
7084
|
-
function sanitizeCSS(css) {
|
|
7085
|
-
let sanitized = decodeCssEscapes2(css);
|
|
7086
|
-
sanitized = sanitized.replace(/@import\s+[^;]+;/gi, "/* @import removed */");
|
|
7087
|
-
sanitized = sanitized.replace(/url\s*\(\s*(?:"[^"]*"|'[^']*'|[^)]*)\s*\)/gi, "/* url() removed */");
|
|
7088
|
-
sanitized = sanitized.replace(/expression\s*\(\s*(?:"[^"]*"|'[^']*'|[^)]*)\s*\)/gi, "/* expression() removed */");
|
|
7089
|
-
sanitized = sanitized.replace(/-moz-binding\s*:[^;]+;/gi, "/* -moz-binding removed */");
|
|
7090
|
-
sanitized = sanitized.replace(/behavior\s*:[^;]+;/gi, "/* behavior removed */");
|
|
7091
|
-
return sanitized;
|
|
7092
|
-
}
|
|
7093
7431
|
function firstCompoundEnd(selector) {
|
|
7094
7432
|
let parens = 0;
|
|
7095
7433
|
let brackets = 0;
|
|
@@ -7251,7 +7589,7 @@ function scopeStylesheet(css, attr) {
|
|
|
7251
7589
|
function scopedStyle(css) {
|
|
7252
7590
|
const id = `sibu-s${_scope.n++}`;
|
|
7253
7591
|
const attr = `data-${id}`;
|
|
7254
|
-
const safeCss =
|
|
7592
|
+
const safeCss = sanitizeStylesheetText(css);
|
|
7255
7593
|
const scopedCSS = scopeStylesheet(safeCss, attr);
|
|
7256
7594
|
if (typeof document !== "undefined") {
|
|
7257
7595
|
const styleEl = document.createElement("style");
|
|
@@ -7277,26 +7615,246 @@ function removeScopedStyle(scopeId) {
|
|
|
7277
7615
|
if (el) el.remove();
|
|
7278
7616
|
}
|
|
7279
7617
|
|
|
7280
|
-
// src/utils/
|
|
7618
|
+
// src/utils/metaRefresh.ts
|
|
7619
|
+
function isAsciiWhitespace(ch) {
|
|
7620
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
7621
|
+
}
|
|
7622
|
+
function trimAsciiWhitespace(value) {
|
|
7623
|
+
let start = 0;
|
|
7624
|
+
let end = value.length;
|
|
7625
|
+
while (start < end && isAsciiWhitespace(value[start])) start++;
|
|
7626
|
+
while (end > start && isAsciiWhitespace(value[end - 1])) end--;
|
|
7627
|
+
return value.slice(start, end);
|
|
7628
|
+
}
|
|
7629
|
+
var forbidden = (reason) => ({ kind: "forbidden", reason });
|
|
7630
|
+
function parseMetaRefreshContent(content) {
|
|
7631
|
+
const raw = trimAsciiWhitespace(stripControlChars(content));
|
|
7632
|
+
if (raw === "") return forbidden(DEV ? "empty content" : "");
|
|
7633
|
+
let i2 = 0;
|
|
7634
|
+
while (i2 < raw.length && raw[i2] >= "0" && raw[i2] <= "9") i2++;
|
|
7635
|
+
if (i2 === 0) return forbidden(DEV ? "missing or non-numeric delay" : "");
|
|
7636
|
+
const delay = Number.parseInt(raw.slice(0, i2), 10);
|
|
7637
|
+
if (!Number.isFinite(delay)) return forbidden(DEV ? "unparseable delay" : "");
|
|
7638
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
7639
|
+
if (i2 === raw.length) return { kind: "delay-only", delay };
|
|
7640
|
+
if (raw[i2] !== ";" && raw[i2] !== ",") return forbidden(DEV ? "unexpected text after delay" : "");
|
|
7641
|
+
i2++;
|
|
7642
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
7643
|
+
const keyStart = i2;
|
|
7644
|
+
while (i2 < raw.length && !isAsciiWhitespace(raw[i2]) && raw[i2] !== "=") i2++;
|
|
7645
|
+
const key = raw.slice(keyStart, i2).toLowerCase();
|
|
7646
|
+
if (key !== "url") return forbidden(DEV ? `unsupported refresh key ${JSON.stringify(key)}` : "");
|
|
7647
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
7648
|
+
if (raw[i2] !== "=") return forbidden(DEV ? "missing '=' after url" : "");
|
|
7649
|
+
i2++;
|
|
7650
|
+
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
7651
|
+
let destination;
|
|
7652
|
+
const quote2 = raw[i2];
|
|
7653
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
7654
|
+
const close = raw.indexOf(quote2, i2 + 1);
|
|
7655
|
+
if (close === -1) return forbidden(DEV ? "unterminated quoted destination" : "");
|
|
7656
|
+
destination = raw.slice(i2 + 1, close);
|
|
7657
|
+
const rest = trimAsciiWhitespace(raw.slice(close + 1));
|
|
7658
|
+
if (rest !== "") return forbidden(DEV ? "trailing text after quoted destination" : "");
|
|
7659
|
+
} else {
|
|
7660
|
+
destination = trimAsciiWhitespace(raw.slice(i2));
|
|
7661
|
+
if (/[;,]/.test(destination)) return forbidden(DEV ? "multiple refresh assignments" : "");
|
|
7662
|
+
}
|
|
7663
|
+
if (destination === "") return forbidden(DEV ? "empty destination" : "");
|
|
7664
|
+
const sanitizedDestination = sanitizeUrl(destination);
|
|
7665
|
+
if (sanitizedDestination === "") return forbidden(DEV ? "destination uses a disallowed protocol" : "");
|
|
7666
|
+
return { kind: "allowed", delay, destination, sanitizedDestination };
|
|
7667
|
+
}
|
|
7668
|
+
function resolveMetaRefreshPolicy(attributes) {
|
|
7669
|
+
let httpEquiv;
|
|
7670
|
+
let content;
|
|
7671
|
+
let duplicateName;
|
|
7672
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7673
|
+
for (const [key, value] of attributes) {
|
|
7674
|
+
const canonical = canonicalAttrName(key);
|
|
7675
|
+
if (seen.has(canonical)) duplicateName = canonical;
|
|
7676
|
+
seen.add(canonical);
|
|
7677
|
+
if (canonical === "http-equiv") httpEquiv = value;
|
|
7678
|
+
else if (canonical === "content") content = value;
|
|
7679
|
+
}
|
|
7680
|
+
if (duplicateName !== void 0) {
|
|
7681
|
+
return forbidden(DEV ? `duplicate case-insensitive attribute ${JSON.stringify(duplicateName)}` : "");
|
|
7682
|
+
}
|
|
7683
|
+
if (typeof httpEquiv !== "string") return { kind: "not-refresh" };
|
|
7684
|
+
if (trimAsciiWhitespace(stripControlChars(httpEquiv)).toLowerCase() !== "refresh") {
|
|
7685
|
+
return { kind: "not-refresh" };
|
|
7686
|
+
}
|
|
7687
|
+
if (typeof content !== "string") return { kind: "not-refresh" };
|
|
7688
|
+
return parseMetaRefreshContent(content);
|
|
7689
|
+
}
|
|
7690
|
+
function normalizeMetaAttributes(props) {
|
|
7691
|
+
const out = /* @__PURE__ */ new Map();
|
|
7692
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7693
|
+
for (const key of Object.keys(props)) {
|
|
7694
|
+
const canonical = canonicalAttrName(key);
|
|
7695
|
+
if (seen.has(canonical)) return null;
|
|
7696
|
+
seen.add(canonical);
|
|
7697
|
+
out.set(key, props[key]);
|
|
7698
|
+
}
|
|
7699
|
+
return out;
|
|
7700
|
+
}
|
|
7701
|
+
function isForbiddenMetaEntry(props) {
|
|
7702
|
+
const normalized = normalizeMetaAttributes(props);
|
|
7703
|
+
if (normalized === null) return true;
|
|
7704
|
+
return resolveMetaRefreshPolicy(normalized).kind === "forbidden";
|
|
7705
|
+
}
|
|
7706
|
+
|
|
7707
|
+
// src/utils/elementPolicy.ts
|
|
7281
7708
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
7282
7709
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
7710
|
+
var BLOCKED_ELEMENTS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
7711
|
+
function canonicalTagName(tag) {
|
|
7712
|
+
return canonicalAttrName(tag);
|
|
7713
|
+
}
|
|
7714
|
+
function isBlockedElement(tag) {
|
|
7715
|
+
return BLOCKED_ELEMENTS.has(canonicalTagName(tag));
|
|
7716
|
+
}
|
|
7717
|
+
var CODE_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
7718
|
+
function isCodeTextElement(tag) {
|
|
7719
|
+
return CODE_TEXT_ELEMENTS.has(canonicalTagName(tag));
|
|
7720
|
+
}
|
|
7721
|
+
var ContextualRefusal = {
|
|
7722
|
+
None: 0,
|
|
7723
|
+
/** The element would carry a refresh directive the shared policy forbids. */
|
|
7724
|
+
MetaRefreshForbidden: 1,
|
|
7725
|
+
/** A `<meta>` with a reactive binding may not carry any refresh directive. */
|
|
7726
|
+
MetaRefreshReactive: 2,
|
|
7727
|
+
/** A runtime value may not choose which program a `<script>` runs. */
|
|
7728
|
+
ScriptSource: 3,
|
|
7729
|
+
/** An SVG animation may not target a URL, handler or document attribute. */
|
|
7730
|
+
AnimationTarget: 4,
|
|
7731
|
+
/** A runtime-written `href` may not become an applied stylesheet. */
|
|
7732
|
+
StylesheetSource: 5
|
|
7733
|
+
};
|
|
7734
|
+
var SCRIPT_SOURCE_ATTRIBUTES = /* @__PURE__ */ new Set(["src", "href", "xlink:href", "type", "language"]);
|
|
7735
|
+
var SVG_ANIMATION_ELEMENTS = /* @__PURE__ */ new Set(["animate", "set", "animateMotion", "animateTransform", "animateColor"]);
|
|
7736
|
+
var reactiveMetaElements = /* @__PURE__ */ new WeakSet();
|
|
7737
|
+
function isHtmlNamespace(el) {
|
|
7738
|
+
return el.namespaceURI === HTML_NS || el.namespaceURI === null;
|
|
7739
|
+
}
|
|
7740
|
+
function metaSnapshot(el, canonical, value) {
|
|
7741
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
7742
|
+
const attrs = el.attributes;
|
|
7743
|
+
for (let i2 = 0; i2 < attrs.length; i2++) {
|
|
7744
|
+
const attr = attrs[i2];
|
|
7745
|
+
if (attr.name === canonical) continue;
|
|
7746
|
+
snapshot.set(attr.name, attr.value);
|
|
7747
|
+
}
|
|
7748
|
+
if (canonical !== null && value !== null) snapshot.set(canonical, value);
|
|
7749
|
+
return snapshot;
|
|
7750
|
+
}
|
|
7751
|
+
function claimReactiveMeta(el) {
|
|
7752
|
+
if (reactiveMetaElements.has(el)) return;
|
|
7753
|
+
reactiveMetaElements.add(el);
|
|
7754
|
+
if (el.getAttribute("content") === null) return;
|
|
7755
|
+
if (resolveMetaRefreshPolicy(metaSnapshot(el, null, null)).kind !== "not-refresh") {
|
|
7756
|
+
el.removeAttribute("content");
|
|
7757
|
+
}
|
|
7758
|
+
}
|
|
7759
|
+
function metaRefusal(el, name, value, origin) {
|
|
7760
|
+
if (!isHtmlNamespace(el)) return ContextualRefusal.None;
|
|
7761
|
+
const canonical = canonicalAttrName(name);
|
|
7762
|
+
if (canonical !== "http-equiv" && canonical !== "content") return ContextualRefusal.None;
|
|
7763
|
+
if (origin === "reactive") claimReactiveMeta(el);
|
|
7764
|
+
if (value === null) return ContextualRefusal.None;
|
|
7765
|
+
if (canonical === "content" && !el.hasAttribute("http-equiv")) return ContextualRefusal.None;
|
|
7766
|
+
const decision = resolveMetaRefreshPolicy(metaSnapshot(el, canonical, value));
|
|
7767
|
+
if (decision.kind === "forbidden") return ContextualRefusal.MetaRefreshForbidden;
|
|
7768
|
+
if (decision.kind !== "not-refresh" && reactiveMetaElements.has(el)) return ContextualRefusal.MetaRefreshReactive;
|
|
7769
|
+
return ContextualRefusal.None;
|
|
7770
|
+
}
|
|
7771
|
+
function animationRefusal(name, value) {
|
|
7772
|
+
if (value === null || canonicalAttrName(name) !== "attributename") return ContextualRefusal.None;
|
|
7773
|
+
const target = stripControlChars(value);
|
|
7774
|
+
return isUrlAttribute(target) || isEventHandlerAttr(target) || isHtmlContentAttribute(target) ? ContextualRefusal.AnimationTarget : ContextualRefusal.None;
|
|
7775
|
+
}
|
|
7776
|
+
var runtimeHrefLinks = /* @__PURE__ */ new WeakSet();
|
|
7777
|
+
function relHasStylesheet(rel) {
|
|
7778
|
+
if (rel === null) return false;
|
|
7779
|
+
const lower = canonicalAttrName(rel);
|
|
7780
|
+
if (!lower.includes("stylesheet")) return false;
|
|
7781
|
+
const tokens = lower.split(/[\t\n\f\r ]+/);
|
|
7782
|
+
for (let i2 = 0; i2 < tokens.length; i2++) if (tokens[i2] === "stylesheet") return true;
|
|
7783
|
+
return false;
|
|
7784
|
+
}
|
|
7785
|
+
function stylesheetRefusal(el, name, value, origin) {
|
|
7786
|
+
if (!isHtmlNamespace(el)) return ContextualRefusal.None;
|
|
7787
|
+
const canonical = canonicalAttrName(name);
|
|
7788
|
+
if (canonical === "href") {
|
|
7789
|
+
if (origin === "static" || value === null) return ContextualRefusal.None;
|
|
7790
|
+
if (relHasStylesheet(el.getAttribute("rel"))) return ContextualRefusal.StylesheetSource;
|
|
7791
|
+
runtimeHrefLinks.add(el);
|
|
7792
|
+
return ContextualRefusal.None;
|
|
7793
|
+
}
|
|
7794
|
+
if (canonical === "rel") {
|
|
7795
|
+
if (!relHasStylesheet(value)) return ContextualRefusal.None;
|
|
7796
|
+
return runtimeHrefLinks.has(el) && el.hasAttribute("href") ? ContextualRefusal.StylesheetSource : ContextualRefusal.None;
|
|
7797
|
+
}
|
|
7798
|
+
return ContextualRefusal.None;
|
|
7799
|
+
}
|
|
7800
|
+
function contextualAttributeRefusal(el, name, value, origin) {
|
|
7801
|
+
const local = el.localName;
|
|
7802
|
+
if (local === "meta") return metaRefusal(el, name, value, origin);
|
|
7803
|
+
if (local === "link") return stylesheetRefusal(el, name, value, origin);
|
|
7804
|
+
if (local === "script") {
|
|
7805
|
+
if (origin === "static" || value === null) return ContextualRefusal.None;
|
|
7806
|
+
return SCRIPT_SOURCE_ATTRIBUTES.has(canonicalAttrName(name)) ? ContextualRefusal.ScriptSource : ContextualRefusal.None;
|
|
7807
|
+
}
|
|
7808
|
+
if (SVG_ANIMATION_ELEMENTS.has(local) && el.namespaceURI === SVG_NS) return animationRefusal(name, value);
|
|
7809
|
+
return ContextualRefusal.None;
|
|
7810
|
+
}
|
|
7811
|
+
function settleAttributeProvenance(el, name, origin) {
|
|
7812
|
+
if (el.localName !== "link" || canonicalAttrName(name) !== "href") return;
|
|
7813
|
+
if (origin !== "static" && el.hasAttribute("href")) runtimeHrefLinks.add(el);
|
|
7814
|
+
else runtimeHrefLinks.delete(el);
|
|
7815
|
+
}
|
|
7816
|
+
function isForbiddenMetaSnapshot(attributes) {
|
|
7817
|
+
return resolveMetaRefreshPolicy(attributes).kind === "forbidden";
|
|
7818
|
+
}
|
|
7819
|
+
|
|
7820
|
+
// src/utils/setSafeAttribute.ts
|
|
7821
|
+
var HTML_NS2 = "http://www.w3.org/1999/xhtml";
|
|
7822
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
7283
7823
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
7284
7824
|
var XML_NS = "http://www.w3.org/XML/1998/namespace";
|
|
7285
7825
|
var BOOLEAN_IDL_ATTRS = /* @__PURE__ */ new Set(["checked", "disabled", "selected"]);
|
|
7286
7826
|
function isHtmlElement(el) {
|
|
7287
|
-
return el.namespaceURI === null || el.namespaceURI ===
|
|
7827
|
+
return el.namespaceURI === null || el.namespaceURI === HTML_NS2;
|
|
7828
|
+
}
|
|
7829
|
+
function warnContextualRefusal(label2, name, refusal) {
|
|
7830
|
+
devWarnLazy(() => {
|
|
7831
|
+
const reasons = [
|
|
7832
|
+
"",
|
|
7833
|
+
'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)',
|
|
7834
|
+
"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",
|
|
7835
|
+
"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",
|
|
7836
|
+
"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",
|
|
7837
|
+
'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'
|
|
7838
|
+
];
|
|
7839
|
+
return `${label2}: refusing "${name}" in this element's context \u2014 ${reasons[refusal]}. The write was not performed.`;
|
|
7840
|
+
});
|
|
7288
7841
|
}
|
|
7289
7842
|
function setProp(el, key, val) {
|
|
7290
7843
|
el[key] = val;
|
|
7291
7844
|
}
|
|
7292
7845
|
function namespaceFor(el, name) {
|
|
7293
|
-
if (el.namespaceURI !==
|
|
7846
|
+
if (el.namespaceURI !== SVG_NS2) return null;
|
|
7294
7847
|
const lower = name.toLowerCase();
|
|
7295
7848
|
if (lower.startsWith("xlink:")) return XLINK_NS;
|
|
7296
7849
|
if (lower.startsWith("xml:")) return XML_NS;
|
|
7297
7850
|
return null;
|
|
7298
7851
|
}
|
|
7299
7852
|
function setSafeAttribute(el, name, value, options = {}) {
|
|
7853
|
+
const written = commitSafeAttribute(el, name, value, options);
|
|
7854
|
+
if (el.localName === "link") settleAttributeProvenance(el, name, options.reactive ? "reactive" : "runtime");
|
|
7855
|
+
return written;
|
|
7856
|
+
}
|
|
7857
|
+
function commitSafeAttribute(el, name, value, options) {
|
|
7300
7858
|
const ns = namespaceFor(el, name);
|
|
7301
7859
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
7302
7860
|
if (isEventHandlerAttr(name)) {
|
|
@@ -7309,6 +7867,14 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
7309
7867
|
else el.removeAttribute(name);
|
|
7310
7868
|
return false;
|
|
7311
7869
|
}
|
|
7870
|
+
const pending = value == null || value === false ? null : value === true ? "" : String(value);
|
|
7871
|
+
const refusal = contextualAttributeRefusal(el, name, pending, options.reactive ? "reactive" : "runtime");
|
|
7872
|
+
if (refusal !== ContextualRefusal.None) {
|
|
7873
|
+
warnContextualRefusal(options.label ?? "setSafeAttribute", name, refusal);
|
|
7874
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
7875
|
+
else el.removeAttribute(name);
|
|
7876
|
+
return false;
|
|
7877
|
+
}
|
|
7312
7878
|
if (value == null) {
|
|
7313
7879
|
if (ns) el.removeAttributeNS(ns, localName);
|
|
7314
7880
|
else el.removeAttribute(name);
|
|
@@ -7352,7 +7918,12 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
7352
7918
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
7353
7919
|
return true;
|
|
7354
7920
|
}
|
|
7355
|
-
const safe =
|
|
7921
|
+
const safe = str === "" ? "" : resolveAttributeValue(name, str, { element: el });
|
|
7922
|
+
if (safe === null) {
|
|
7923
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
7924
|
+
else el.removeAttribute(name);
|
|
7925
|
+
return true;
|
|
7926
|
+
}
|
|
7356
7927
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
7357
7928
|
if (current === safe) return true;
|
|
7358
7929
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -7375,7 +7946,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
7375
7946
|
reportError(err, { phase: "binding", name: `bindAttribute("${attr}")`, node: el });
|
|
7376
7947
|
return;
|
|
7377
7948
|
}
|
|
7378
|
-
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")
|
|
7949
|
+
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")`, reactive: true });
|
|
7379
7950
|
}
|
|
7380
7951
|
return reactiveBinding2(commit, el);
|
|
7381
7952
|
}
|
|
@@ -7412,7 +7983,7 @@ function bindBoolAttr(el, attr, getter) {
|
|
|
7412
7983
|
reportError(err, { phase: "binding", name: "bindBoolAttr", node: el });
|
|
7413
7984
|
return;
|
|
7414
7985
|
}
|
|
7415
|
-
setSafeAttribute(el, attr, Boolean(value), { label: "bindBoolAttr" });
|
|
7986
|
+
setSafeAttribute(el, attr, Boolean(value), { label: "bindBoolAttr", reactive: true });
|
|
7416
7987
|
}
|
|
7417
7988
|
return reactiveBinding2(commit, el);
|
|
7418
7989
|
}
|
|
@@ -7965,6 +8536,9 @@ var DOMPool = class {
|
|
|
7965
8536
|
* Get a recycled element or create a new one.
|
|
7966
8537
|
*/
|
|
7967
8538
|
acquire(tag) {
|
|
8539
|
+
if (isBlockedElement(tag)) {
|
|
8540
|
+
throw new Error(`DOMPool: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
8541
|
+
}
|
|
7968
8542
|
const pool = this.pools.get(tag);
|
|
7969
8543
|
if (pool && pool.length > 0) {
|
|
7970
8544
|
const el = pool.pop();
|
|
@@ -8070,10 +8644,19 @@ function prefetch(url) {
|
|
|
8070
8644
|
}
|
|
8071
8645
|
function preloadImage(src) {
|
|
8072
8646
|
return new Promise((resolve, reject) => {
|
|
8647
|
+
const safe = sanitizeUrl(String(src));
|
|
8648
|
+
if (!safe) {
|
|
8649
|
+
reject(
|
|
8650
|
+
new Error(
|
|
8651
|
+
String(src).trim() === "" ? "preloadImage: no image URL was given." : "preloadImage: refusing an image URL outside the URL policy."
|
|
8652
|
+
)
|
|
8653
|
+
);
|
|
8654
|
+
return;
|
|
8655
|
+
}
|
|
8073
8656
|
const img2 = new Image();
|
|
8074
8657
|
img2.onload = () => resolve(img2);
|
|
8075
8658
|
img2.onerror = reject;
|
|
8076
|
-
img2.src =
|
|
8659
|
+
img2.src = safe;
|
|
8077
8660
|
});
|
|
8078
8661
|
}
|
|
8079
8662
|
|
|
@@ -8099,95 +8682,6 @@ function noSideEffect(fn) {
|
|
|
8099
8682
|
return fn;
|
|
8100
8683
|
}
|
|
8101
8684
|
|
|
8102
|
-
// src/utils/metaRefresh.ts
|
|
8103
|
-
function isAsciiWhitespace(ch) {
|
|
8104
|
-
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
8105
|
-
}
|
|
8106
|
-
function trimAsciiWhitespace(value) {
|
|
8107
|
-
let start = 0;
|
|
8108
|
-
let end = value.length;
|
|
8109
|
-
while (start < end && isAsciiWhitespace(value[start])) start++;
|
|
8110
|
-
while (end > start && isAsciiWhitespace(value[end - 1])) end--;
|
|
8111
|
-
return value.slice(start, end);
|
|
8112
|
-
}
|
|
8113
|
-
var forbidden = (reason) => ({ kind: "forbidden", reason });
|
|
8114
|
-
function parseMetaRefreshContent(content) {
|
|
8115
|
-
const raw = trimAsciiWhitespace(stripControlChars(content));
|
|
8116
|
-
if (raw === "") return forbidden("empty content");
|
|
8117
|
-
let i2 = 0;
|
|
8118
|
-
while (i2 < raw.length && raw[i2] >= "0" && raw[i2] <= "9") i2++;
|
|
8119
|
-
if (i2 === 0) return forbidden("missing or non-numeric delay");
|
|
8120
|
-
const delay = Number.parseInt(raw.slice(0, i2), 10);
|
|
8121
|
-
if (!Number.isFinite(delay)) return forbidden("unparseable delay");
|
|
8122
|
-
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
8123
|
-
if (i2 === raw.length) return { kind: "delay-only", delay };
|
|
8124
|
-
if (raw[i2] !== ";" && raw[i2] !== ",") return forbidden("unexpected text after delay");
|
|
8125
|
-
i2++;
|
|
8126
|
-
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
8127
|
-
const keyStart = i2;
|
|
8128
|
-
while (i2 < raw.length && !isAsciiWhitespace(raw[i2]) && raw[i2] !== "=") i2++;
|
|
8129
|
-
const key = raw.slice(keyStart, i2).toLowerCase();
|
|
8130
|
-
if (key !== "url") return forbidden(`unsupported refresh key ${JSON.stringify(key)}`);
|
|
8131
|
-
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
8132
|
-
if (raw[i2] !== "=") return forbidden("missing '=' after url");
|
|
8133
|
-
i2++;
|
|
8134
|
-
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
8135
|
-
let destination;
|
|
8136
|
-
const quote2 = raw[i2];
|
|
8137
|
-
if (quote2 === '"' || quote2 === "'") {
|
|
8138
|
-
const close = raw.indexOf(quote2, i2 + 1);
|
|
8139
|
-
if (close === -1) return forbidden("unterminated quoted destination");
|
|
8140
|
-
destination = raw.slice(i2 + 1, close);
|
|
8141
|
-
const rest = trimAsciiWhitespace(raw.slice(close + 1));
|
|
8142
|
-
if (rest !== "") return forbidden("trailing text after quoted destination");
|
|
8143
|
-
} else {
|
|
8144
|
-
destination = trimAsciiWhitespace(raw.slice(i2));
|
|
8145
|
-
if (/[;,]/.test(destination)) return forbidden("multiple refresh assignments");
|
|
8146
|
-
}
|
|
8147
|
-
if (destination === "") return forbidden("empty destination");
|
|
8148
|
-
const sanitizedDestination = sanitizeUrl(destination);
|
|
8149
|
-
if (sanitizedDestination === "") return forbidden("destination uses a disallowed protocol");
|
|
8150
|
-
return { kind: "allowed", delay, destination, sanitizedDestination };
|
|
8151
|
-
}
|
|
8152
|
-
function resolveMetaRefreshPolicy(attributes) {
|
|
8153
|
-
let httpEquiv;
|
|
8154
|
-
let content;
|
|
8155
|
-
let duplicateName;
|
|
8156
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8157
|
-
for (const [key, value] of attributes) {
|
|
8158
|
-
const canonical = canonicalAttrName(key);
|
|
8159
|
-
if (seen.has(canonical)) duplicateName = canonical;
|
|
8160
|
-
seen.add(canonical);
|
|
8161
|
-
if (canonical === "http-equiv") httpEquiv = value;
|
|
8162
|
-
else if (canonical === "content") content = value;
|
|
8163
|
-
}
|
|
8164
|
-
if (duplicateName !== void 0) {
|
|
8165
|
-
return forbidden(`duplicate case-insensitive attribute ${JSON.stringify(duplicateName)}`);
|
|
8166
|
-
}
|
|
8167
|
-
if (typeof httpEquiv !== "string") return { kind: "not-refresh" };
|
|
8168
|
-
if (trimAsciiWhitespace(stripControlChars(httpEquiv)).toLowerCase() !== "refresh") {
|
|
8169
|
-
return { kind: "not-refresh" };
|
|
8170
|
-
}
|
|
8171
|
-
if (typeof content !== "string") return { kind: "not-refresh" };
|
|
8172
|
-
return parseMetaRefreshContent(content);
|
|
8173
|
-
}
|
|
8174
|
-
function normalizeMetaAttributes(props) {
|
|
8175
|
-
const out = /* @__PURE__ */ new Map();
|
|
8176
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8177
|
-
for (const key of Object.keys(props)) {
|
|
8178
|
-
const canonical = canonicalAttrName(key);
|
|
8179
|
-
if (seen.has(canonical)) return null;
|
|
8180
|
-
seen.add(canonical);
|
|
8181
|
-
out.set(key, props[key]);
|
|
8182
|
-
}
|
|
8183
|
-
return out;
|
|
8184
|
-
}
|
|
8185
|
-
function isForbiddenMetaEntry(props) {
|
|
8186
|
-
const normalized = normalizeMetaAttributes(props);
|
|
8187
|
-
if (normalized === null) return true;
|
|
8188
|
-
return resolveMetaRefreshPolicy(normalized).kind === "forbidden";
|
|
8189
|
-
}
|
|
8190
|
-
|
|
8191
8685
|
// src/utils/headEntry.ts
|
|
8192
8686
|
var SAFE_HEAD_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
8193
8687
|
function isEmittableHeadAttrName(name) {
|
|
@@ -8198,9 +8692,7 @@ function isEmittableHeadAttrName(name) {
|
|
|
8198
8692
|
return true;
|
|
8199
8693
|
}
|
|
8200
8694
|
function sanitizeHeadAttrValue(canonical, value) {
|
|
8201
|
-
|
|
8202
|
-
const safe = sanitizeAttributeString(canonical, value);
|
|
8203
|
-
return safe === "" ? null : safe;
|
|
8695
|
+
return resolveAttributeValue(canonical, value);
|
|
8204
8696
|
}
|
|
8205
8697
|
function findDuplicateAttributeName(names) {
|
|
8206
8698
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8257,15 +8749,9 @@ function serializeHeadEntry(tag, attrs) {
|
|
|
8257
8749
|
}
|
|
8258
8750
|
|
|
8259
8751
|
// src/platform/ssr.ts
|
|
8260
|
-
function isPolicyAttr(lowerName) {
|
|
8261
|
-
return isPolicyAttribute(lowerName);
|
|
8262
|
-
}
|
|
8263
8752
|
function isForbiddenSsrAttr(lowerName) {
|
|
8264
8753
|
return isHtmlContentAttribute(lowerName);
|
|
8265
8754
|
}
|
|
8266
|
-
function sanitizeSsrAttributeValue(lowerName, value) {
|
|
8267
|
-
return sanitizeAttributeString(lowerName, value);
|
|
8268
|
-
}
|
|
8269
8755
|
var SAFE_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
8270
8756
|
function isSafeAttrName(name) {
|
|
8271
8757
|
return SAFE_ATTR_NAME.test(name);
|
|
@@ -8296,6 +8782,64 @@ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
8296
8782
|
"track",
|
|
8297
8783
|
"wbr"
|
|
8298
8784
|
]);
|
|
8785
|
+
function findNativeGetter(proto, name) {
|
|
8786
|
+
for (let p2 = proto; p2; p2 = Object.getPrototypeOf(p2)) {
|
|
8787
|
+
const get = Object.getOwnPropertyDescriptor(p2, name)?.get;
|
|
8788
|
+
if (get) return get;
|
|
8789
|
+
}
|
|
8790
|
+
return null;
|
|
8791
|
+
}
|
|
8792
|
+
var nativeAccessorsByRealm = /* @__PURE__ */ new WeakMap();
|
|
8793
|
+
function nativeAccessors() {
|
|
8794
|
+
const realm = Element;
|
|
8795
|
+
let accessors = nativeAccessorsByRealm.get(realm);
|
|
8796
|
+
if (!accessors) {
|
|
8797
|
+
accessors = {
|
|
8798
|
+
attributes: findNativeGetter(Element.prototype, "attributes"),
|
|
8799
|
+
tagName: findNativeGetter(Element.prototype, "tagName"),
|
|
8800
|
+
childNodes: findNativeGetter(Node.prototype, "childNodes"),
|
|
8801
|
+
getAttribute: Element.prototype.getAttribute
|
|
8802
|
+
};
|
|
8803
|
+
nativeAccessorsByRealm.set(realm, accessors);
|
|
8804
|
+
}
|
|
8805
|
+
return accessors;
|
|
8806
|
+
}
|
|
8807
|
+
function attributesOf(el) {
|
|
8808
|
+
const get = nativeAccessors().attributes;
|
|
8809
|
+
return get ? get.call(el) : el.attributes;
|
|
8810
|
+
}
|
|
8811
|
+
function tagNameOf(el) {
|
|
8812
|
+
const get = nativeAccessors().tagName;
|
|
8813
|
+
return get ? get.call(el) : el.tagName;
|
|
8814
|
+
}
|
|
8815
|
+
function childNodesOf(node) {
|
|
8816
|
+
const get = nativeAccessors().childNodes;
|
|
8817
|
+
return get ? get.call(node) : node.childNodes;
|
|
8818
|
+
}
|
|
8819
|
+
function getAttributeOf(el, name) {
|
|
8820
|
+
return nativeAccessors().getAttribute.call(el, name);
|
|
8821
|
+
}
|
|
8822
|
+
function serializeOpenTag(element, tag) {
|
|
8823
|
+
let html2 = `<${tag}`;
|
|
8824
|
+
const meta2 = tag === "meta" ? /* @__PURE__ */ new Map() : null;
|
|
8825
|
+
const attrs = attributesOf(element);
|
|
8826
|
+
for (let i2 = 0; i2 < attrs.length; i2++) {
|
|
8827
|
+
const attr = attrs[i2];
|
|
8828
|
+
const rawName = attr.name;
|
|
8829
|
+
if (!isSafeAttrName(rawName)) continue;
|
|
8830
|
+
if (isEventHandlerAttr(rawName)) continue;
|
|
8831
|
+
if (isForbiddenSsrAttr(rawName)) continue;
|
|
8832
|
+
const value = resolveAttributeValue(rawName.toLowerCase(), attr.value);
|
|
8833
|
+
if (value === null) continue;
|
|
8834
|
+
meta2?.set(rawName, value);
|
|
8835
|
+
html2 += ` ${rawName}="${escapeAttr(value)}"`;
|
|
8836
|
+
}
|
|
8837
|
+
if (meta2 && isForbiddenMetaSnapshot(meta2)) return null;
|
|
8838
|
+
if (!getAttributeOf(element, "data-sibu-hydrate")) {
|
|
8839
|
+
html2 += ` data-sibu-ssr="true"`;
|
|
8840
|
+
}
|
|
8841
|
+
return html2;
|
|
8842
|
+
}
|
|
8299
8843
|
function renderToString(element) {
|
|
8300
8844
|
if (element instanceof DocumentFragment) {
|
|
8301
8845
|
return Array.from(element.childNodes).map((child) => {
|
|
@@ -8315,35 +8859,21 @@ function renderToString(element) {
|
|
|
8315
8859
|
if (!(element instanceof HTMLElement)) {
|
|
8316
8860
|
return escapeHtml(element.textContent || "");
|
|
8317
8861
|
}
|
|
8318
|
-
const tag = element.
|
|
8319
|
-
if (tag
|
|
8862
|
+
const tag = tagNameOf(element).toLowerCase();
|
|
8863
|
+
if (isCodeTextElement(tag)) {
|
|
8320
8864
|
return DEV ? `<!--ssr:${tag}-stripped-->` : "";
|
|
8321
8865
|
}
|
|
8322
8866
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
8323
8867
|
return DEV ? "<!--ssr:invalid-tag-->" : "";
|
|
8324
8868
|
}
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8328
|
-
if (!isSafeAttrName(rawName)) continue;
|
|
8329
|
-
if (isEventHandlerAttr(rawName)) continue;
|
|
8330
|
-
if (isForbiddenSsrAttr(rawName)) continue;
|
|
8331
|
-
const lowerName = rawName.toLowerCase();
|
|
8332
|
-
let value = attr.value;
|
|
8333
|
-
if (isPolicyAttr(lowerName)) {
|
|
8334
|
-
value = sanitizeSsrAttributeValue(lowerName, value);
|
|
8335
|
-
if (!value) continue;
|
|
8336
|
-
}
|
|
8337
|
-
html2 += ` ${rawName}="${escapeAttr(value)}"`;
|
|
8338
|
-
}
|
|
8339
|
-
if (element.dataset && !element.dataset.sibuHydrate) {
|
|
8340
|
-
html2 += ` data-sibu-ssr="true"`;
|
|
8341
|
-
}
|
|
8869
|
+
const openTag = serializeOpenTag(element, tag);
|
|
8870
|
+
if (openTag === null) return DEV ? `<!--ssr:${tag}-stripped-->` : "";
|
|
8871
|
+
let html2 = openTag;
|
|
8342
8872
|
if (VOID_ELEMENTS.has(tag)) {
|
|
8343
8873
|
return `${html2} />`;
|
|
8344
8874
|
}
|
|
8345
8875
|
html2 += ">";
|
|
8346
|
-
for (const child of Array.from(element
|
|
8876
|
+
for (const child of Array.from(childNodesOf(element))) {
|
|
8347
8877
|
try {
|
|
8348
8878
|
html2 += renderToString(child);
|
|
8349
8879
|
} catch (err) {
|
|
@@ -8493,12 +9023,8 @@ function buildAttrString(attrs, { allowEventHandlers = false } = {}) {
|
|
|
8493
9023
|
if (!isSafeAttrName(rawKey)) continue;
|
|
8494
9024
|
if (!allowEventHandlers && isEventHandlerAttr(rawKey)) continue;
|
|
8495
9025
|
if (isForbiddenSsrAttr(rawKey)) continue;
|
|
8496
|
-
const
|
|
8497
|
-
|
|
8498
|
-
if (isPolicyAttr(lowerKey)) {
|
|
8499
|
-
value = sanitizeSsrAttributeValue(lowerKey, value);
|
|
8500
|
-
if (!value) continue;
|
|
8501
|
-
}
|
|
9026
|
+
const value = resolveAttributeValue(rawKey.toLowerCase(), String(attrs[rawKey]));
|
|
9027
|
+
if (value === null) continue;
|
|
8502
9028
|
out.push(`${rawKey}="${escapeAttr(value)}"`);
|
|
8503
9029
|
}
|
|
8504
9030
|
return out.join(" ");
|
|
@@ -8561,8 +9087,8 @@ async function* renderToStream(element) {
|
|
|
8561
9087
|
yield escapeHtml(element.textContent || "");
|
|
8562
9088
|
return;
|
|
8563
9089
|
}
|
|
8564
|
-
const tag = element.
|
|
8565
|
-
if (tag
|
|
9090
|
+
const tag = tagNameOf(element).toLowerCase();
|
|
9091
|
+
if (isCodeTextElement(tag)) {
|
|
8566
9092
|
if (DEV) yield `<!--ssr:${tag}-stripped-->`;
|
|
8567
9093
|
return;
|
|
8568
9094
|
}
|
|
@@ -8570,29 +9096,17 @@ async function* renderToStream(element) {
|
|
|
8570
9096
|
if (DEV) yield "<!--ssr:invalid-tag-->";
|
|
8571
9097
|
return;
|
|
8572
9098
|
}
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
if (isEventHandlerAttr(rawName)) continue;
|
|
8578
|
-
if (isForbiddenSsrAttr(rawName)) continue;
|
|
8579
|
-
const lowerName = rawName.toLowerCase();
|
|
8580
|
-
let value = attr.value;
|
|
8581
|
-
if (isPolicyAttr(lowerName)) {
|
|
8582
|
-
value = sanitizeSsrAttributeValue(lowerName, value);
|
|
8583
|
-
if (!value) continue;
|
|
8584
|
-
}
|
|
8585
|
-
openTag += ` ${rawName}="${escapeAttr(value)}"`;
|
|
8586
|
-
}
|
|
8587
|
-
if (element.dataset && !element.dataset.sibuHydrate) {
|
|
8588
|
-
openTag += ` data-sibu-ssr="true"`;
|
|
9099
|
+
const openTag = serializeOpenTag(element, tag);
|
|
9100
|
+
if (openTag === null) {
|
|
9101
|
+
if (DEV) yield `<!--ssr:${tag}-stripped-->`;
|
|
9102
|
+
return;
|
|
8589
9103
|
}
|
|
8590
9104
|
if (VOID_ELEMENTS.has(tag)) {
|
|
8591
9105
|
yield `${openTag} />`;
|
|
8592
9106
|
return;
|
|
8593
9107
|
}
|
|
8594
9108
|
yield `${openTag}>`;
|
|
8595
|
-
for (const child of Array.from(element
|
|
9109
|
+
for (const child of Array.from(childNodesOf(element))) {
|
|
8596
9110
|
try {
|
|
8597
9111
|
yield* renderToStream(child);
|
|
8598
9112
|
} catch (err) {
|
|
@@ -8777,8 +9291,7 @@ function deserializeState(validate) {
|
|
|
8777
9291
|
"[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
|
|
8778
9292
|
);
|
|
8779
9293
|
}
|
|
8780
|
-
const
|
|
8781
|
-
const raw = w[SSR_DATA_ATTR];
|
|
9294
|
+
const raw = readOwnGlobal(SSR_DATA_ATTR);
|
|
8782
9295
|
if (raw === void 0) return void 0;
|
|
8783
9296
|
if (validate && !validate(raw)) return void 0;
|
|
8784
9297
|
return raw;
|
|
@@ -9365,7 +9878,7 @@ function setCanonical(url) {
|
|
|
9365
9878
|
}
|
|
9366
9879
|
|
|
9367
9880
|
// src/platform/customElement.ts
|
|
9368
|
-
var
|
|
9881
|
+
var SVG_NS3 = "http://www.w3.org/2000/svg";
|
|
9369
9882
|
var MAX_RENDER_PASSES = 10;
|
|
9370
9883
|
var ABANDONED_RENDER = /* @__PURE__ */ Symbol("sibujs.defineElement.abandonedRender");
|
|
9371
9884
|
function defineElement(name, component, options = {}) {
|
|
@@ -9514,7 +10027,10 @@ function defineElement(name, component, options = {}) {
|
|
|
9514
10027
|
customElements.define(name, SibuElement);
|
|
9515
10028
|
}
|
|
9516
10029
|
function svgElement(tag, props = {}, ...nodes) {
|
|
9517
|
-
|
|
10030
|
+
if (isBlockedElement(tag)) {
|
|
10031
|
+
throw new Error(`svgElement: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
10032
|
+
}
|
|
10033
|
+
const el = document.createElementNS(SVG_NS3, tag);
|
|
9518
10034
|
for (const [key, value] of Object.entries(props)) {
|
|
9519
10035
|
if (key === "nodes") continue;
|
|
9520
10036
|
if (typeof value === "function" && isEventHandlerAttr(key)) {
|
|
@@ -9539,7 +10055,16 @@ function toError(err) {
|
|
|
9539
10055
|
if (err !== null && typeof err === "object" && "name" in err && "message" in err) return err;
|
|
9540
10056
|
return new Error(String(err));
|
|
9541
10057
|
}
|
|
10058
|
+
function workerSource(fn, api) {
|
|
10059
|
+
if (typeof fn !== "function") {
|
|
10060
|
+
throw new TypeError(
|
|
10061
|
+
`${api}: expected a function, got ${typeof fn}. Worker code must be a function defined in your source \u2014 a string would be evaluated as code.`
|
|
10062
|
+
);
|
|
10063
|
+
}
|
|
10064
|
+
return Function.prototype.toString.call(fn);
|
|
10065
|
+
}
|
|
9542
10066
|
function worker(workerFn2) {
|
|
10067
|
+
const fnBody = workerSource(workerFn2, "worker");
|
|
9543
10068
|
const [result, setResult] = signal(null);
|
|
9544
10069
|
const [error, setError] = signal(null);
|
|
9545
10070
|
const [loading, setLoading] = signal(false);
|
|
@@ -9555,7 +10080,6 @@ function worker(workerFn2) {
|
|
|
9555
10080
|
if (typeof Worker === "undefined") {
|
|
9556
10081
|
throw new Error("Web Workers are not supported in this environment");
|
|
9557
10082
|
}
|
|
9558
|
-
const fnBody = workerFn2.toString();
|
|
9559
10083
|
const blob = new Blob([`self.onmessage = ${fnBody};`], { type: "application/javascript" });
|
|
9560
10084
|
blobUrl = URL.createObjectURL(blob);
|
|
9561
10085
|
worker2 = new Worker(blobUrl);
|
|
@@ -9604,6 +10128,7 @@ function worker(workerFn2) {
|
|
|
9604
10128
|
return { post, result, error, loading, terminate };
|
|
9605
10129
|
}
|
|
9606
10130
|
function workerFn(fn) {
|
|
10131
|
+
const fnStr = workerSource(fn, "workerFn");
|
|
9607
10132
|
const [loading, setLoading] = signal(false);
|
|
9608
10133
|
let worker2 = null;
|
|
9609
10134
|
let blobUrl = null;
|
|
@@ -9618,7 +10143,6 @@ function workerFn(fn) {
|
|
|
9618
10143
|
if (typeof Worker === "undefined") {
|
|
9619
10144
|
throw new Error("Web Workers are not supported in this environment");
|
|
9620
10145
|
}
|
|
9621
|
-
const fnStr = fn.toString();
|
|
9622
10146
|
const blob = new Blob(
|
|
9623
10147
|
[
|
|
9624
10148
|
`self.onmessage = function(e) {
|
|
@@ -9678,6 +10202,7 @@ function workerFn(fn) {
|
|
|
9678
10202
|
return { run, loading, terminate };
|
|
9679
10203
|
}
|
|
9680
10204
|
function createWorkerPool(workerFn2, poolSize) {
|
|
10205
|
+
const fnBody = workerSource(workerFn2, "createWorkerPool");
|
|
9681
10206
|
const size = poolSize || typeof navigator !== "undefined" && navigator.hardwareConcurrency || 4;
|
|
9682
10207
|
const workers = [];
|
|
9683
10208
|
const queues = [];
|
|
@@ -9736,7 +10261,6 @@ function createWorkerPool(workerFn2, poolSize) {
|
|
|
9736
10261
|
if (typeof Worker === "undefined") {
|
|
9737
10262
|
throw new Error("Web Workers are not supported in this environment");
|
|
9738
10263
|
}
|
|
9739
|
-
const fnBody = workerFn2.toString();
|
|
9740
10264
|
const blob = new Blob([`self.onmessage = ${fnBody};`], { type: "application/javascript" });
|
|
9741
10265
|
blobUrl = URL.createObjectURL(blob);
|
|
9742
10266
|
for (let i2 = 0; i2 < size; i2++) {
|
|
@@ -10133,11 +10657,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
10133
10657
|
}
|
|
10134
10658
|
|
|
10135
10659
|
// src/core/rendering/tagFactory.ts
|
|
10136
|
-
var
|
|
10137
|
-
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
10138
|
-
function isBlockedTag(tag) {
|
|
10139
|
-
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
10140
|
-
}
|
|
10660
|
+
var SVG_NS4 = "http://www.w3.org/2000/svg";
|
|
10141
10661
|
var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
10142
10662
|
"config",
|
|
10143
10663
|
"location",
|
|
@@ -10164,8 +10684,35 @@ function toKebab(prop) {
|
|
|
10164
10684
|
}
|
|
10165
10685
|
function applyStyle(el, style2) {
|
|
10166
10686
|
if (typeof style2 === "function") {
|
|
10687
|
+
const getter = style2;
|
|
10688
|
+
let written = [];
|
|
10689
|
+
let wroteString = false;
|
|
10167
10690
|
const teardown = reactiveBinding2(() => {
|
|
10168
|
-
|
|
10691
|
+
const value = getter();
|
|
10692
|
+
if (value === null || typeof value !== "object") {
|
|
10693
|
+
written = [];
|
|
10694
|
+
wroteString = true;
|
|
10695
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(value), { element: el }));
|
|
10696
|
+
return;
|
|
10697
|
+
}
|
|
10698
|
+
const decl = el.style;
|
|
10699
|
+
if (wroteString) {
|
|
10700
|
+
el.removeAttribute("style");
|
|
10701
|
+
wroteString = false;
|
|
10702
|
+
}
|
|
10703
|
+
const next = [];
|
|
10704
|
+
for (const prop in value) {
|
|
10705
|
+
if (!Object.hasOwn(value, prop)) continue;
|
|
10706
|
+
const val = value[prop];
|
|
10707
|
+
if (val == null) continue;
|
|
10708
|
+
const name = toKebab(prop);
|
|
10709
|
+
next.push(name);
|
|
10710
|
+
decl.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
10711
|
+
}
|
|
10712
|
+
for (let i2 = 0; i2 < written.length; i2++) {
|
|
10713
|
+
if (next.indexOf(written[i2]) === -1) decl.removeProperty(written[i2]);
|
|
10714
|
+
}
|
|
10715
|
+
written = next;
|
|
10169
10716
|
}, el);
|
|
10170
10717
|
registerDisposer(el, teardown);
|
|
10171
10718
|
return;
|
|
@@ -10176,16 +10723,17 @@ function applyStyle(el, style2) {
|
|
|
10176
10723
|
}
|
|
10177
10724
|
const htmlEl = el;
|
|
10178
10725
|
for (const prop in style2) {
|
|
10726
|
+
if (!Object.hasOwn(style2, prop)) continue;
|
|
10179
10727
|
const val = style2[prop];
|
|
10180
10728
|
const name = toKebab(prop);
|
|
10181
10729
|
if (typeof val === "function") {
|
|
10182
10730
|
const getter = val;
|
|
10183
10731
|
const teardown = reactiveBinding2(() => {
|
|
10184
|
-
htmlEl.style.setProperty(name,
|
|
10732
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(getter()), { element: el }));
|
|
10185
10733
|
}, el);
|
|
10186
10734
|
registerDisposer(el, teardown);
|
|
10187
10735
|
} else {
|
|
10188
|
-
htmlEl.style.setProperty(name,
|
|
10736
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
10189
10737
|
}
|
|
10190
10738
|
}
|
|
10191
10739
|
}
|
|
@@ -10196,7 +10744,9 @@ function applyClass(el, cls) {
|
|
|
10196
10744
|
}
|
|
10197
10745
|
if (typeof cls === "function") {
|
|
10198
10746
|
const teardown = reactiveBinding2(() => {
|
|
10199
|
-
|
|
10747
|
+
const value = cls();
|
|
10748
|
+
if (value == null || value === false) el.removeAttribute("class");
|
|
10749
|
+
else el.setAttribute("class", value);
|
|
10200
10750
|
}, el);
|
|
10201
10751
|
registerDisposer(el, teardown);
|
|
10202
10752
|
return;
|
|
@@ -10205,6 +10755,7 @@ function applyClass(el, cls) {
|
|
|
10205
10755
|
let hasReactive = false;
|
|
10206
10756
|
let result = "";
|
|
10207
10757
|
for (const name in obj) {
|
|
10758
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
10208
10759
|
const val = obj[name];
|
|
10209
10760
|
if (typeof val === "function") {
|
|
10210
10761
|
hasReactive = true;
|
|
@@ -10216,6 +10767,7 @@ function applyClass(el, cls) {
|
|
|
10216
10767
|
const update = () => {
|
|
10217
10768
|
let r = "";
|
|
10218
10769
|
for (const name in obj) {
|
|
10770
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
10219
10771
|
const val = obj[name];
|
|
10220
10772
|
const active = typeof val === "function" ? val() : val;
|
|
10221
10773
|
if (active) r = r ? `${r} ${name}` : name;
|
|
@@ -10278,8 +10830,8 @@ function appendChildren(el, nodes) {
|
|
|
10278
10830
|
}
|
|
10279
10831
|
}
|
|
10280
10832
|
}
|
|
10281
|
-
|
|
10282
|
-
const blocked =
|
|
10833
|
+
function tagFactory(tag, ns) {
|
|
10834
|
+
const blocked = isBlockedElement(tag);
|
|
10283
10835
|
return (first, second) => {
|
|
10284
10836
|
if (blocked) {
|
|
10285
10837
|
throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
@@ -10327,7 +10879,9 @@ var tagFactory = (tag, ns) => {
|
|
|
10327
10879
|
const pClass = props.class;
|
|
10328
10880
|
if (pClass != null) applyClass(el, pClass);
|
|
10329
10881
|
const pId = props.id;
|
|
10330
|
-
if (pId
|
|
10882
|
+
if (typeof pId === "function") {
|
|
10883
|
+
registerDisposer(el, bindAttribute(el, "id", pId));
|
|
10884
|
+
} else if (pId != null) {
|
|
10331
10885
|
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
10332
10886
|
devWarn(
|
|
10333
10887
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
@@ -10340,6 +10894,7 @@ var tagFactory = (tag, ns) => {
|
|
|
10340
10894
|
const pOn = props.on;
|
|
10341
10895
|
if (pOn) {
|
|
10342
10896
|
for (const ev in pOn) {
|
|
10897
|
+
if (!Object.hasOwn(pOn, ev)) continue;
|
|
10343
10898
|
const handler = pOn[ev];
|
|
10344
10899
|
if (typeof handler === "function") {
|
|
10345
10900
|
el.addEventListener(ev, handler);
|
|
@@ -10366,6 +10921,7 @@ var tagFactory = (tag, ns) => {
|
|
|
10366
10921
|
continue;
|
|
10367
10922
|
// already handled above / below
|
|
10368
10923
|
default: {
|
|
10924
|
+
if (!Object.hasOwn(props, key)) continue;
|
|
10369
10925
|
const value = props[key];
|
|
10370
10926
|
if (value == null) continue;
|
|
10371
10927
|
if (isEventHandlerAttr(key)) continue;
|
|
@@ -10377,12 +10933,10 @@ var tagFactory = (tag, ns) => {
|
|
|
10377
10933
|
}
|
|
10378
10934
|
}
|
|
10379
10935
|
}
|
|
10380
|
-
if (
|
|
10381
|
-
props.onElement(el);
|
|
10382
|
-
}
|
|
10936
|
+
if (typeof props.onElement === "function") props.onElement(el);
|
|
10383
10937
|
return el;
|
|
10384
10938
|
};
|
|
10385
|
-
}
|
|
10939
|
+
}
|
|
10386
10940
|
|
|
10387
10941
|
// src/core/rendering/html.ts
|
|
10388
10942
|
var html = tagFactory("html");
|
|
@@ -10457,7 +11011,7 @@ var param = tagFactory("param");
|
|
|
10457
11011
|
var picture = tagFactory("picture");
|
|
10458
11012
|
var portal = tagFactory("portal");
|
|
10459
11013
|
var source = tagFactory("source");
|
|
10460
|
-
var svg = tagFactory("svg",
|
|
11014
|
+
var svg = tagFactory("svg", SVG_NS4);
|
|
10461
11015
|
var math = tagFactory("math");
|
|
10462
11016
|
var canvas = tagFactory("canvas");
|
|
10463
11017
|
var noscript = tagFactory("noscript");
|
|
@@ -10498,26 +11052,26 @@ var base = tagFactory("base");
|
|
|
10498
11052
|
var link = tagFactory("link");
|
|
10499
11053
|
var meta = tagFactory("meta");
|
|
10500
11054
|
var style = tagFactory("style");
|
|
10501
|
-
var circle = tagFactory("circle",
|
|
10502
|
-
var ellipse = tagFactory("ellipse",
|
|
10503
|
-
var g = tagFactory("g",
|
|
10504
|
-
var line = tagFactory("line",
|
|
10505
|
-
var path = tagFactory("path",
|
|
10506
|
-
var polygon = tagFactory("polygon",
|
|
10507
|
-
var polyline = tagFactory("polyline",
|
|
10508
|
-
var rect = tagFactory("rect",
|
|
10509
|
-
var text = tagFactory("text",
|
|
10510
|
-
var tspan = tagFactory("tspan",
|
|
10511
|
-
var defs = tagFactory("defs",
|
|
10512
|
-
var clipPath = tagFactory("clipPath",
|
|
10513
|
-
var mask = tagFactory("mask",
|
|
10514
|
-
var pattern = tagFactory("pattern",
|
|
10515
|
-
var linearGradient = tagFactory("linearGradient",
|
|
10516
|
-
var radialGradient = tagFactory("radialGradient",
|
|
10517
|
-
var stop = tagFactory("stop",
|
|
10518
|
-
var use = tagFactory("use",
|
|
10519
|
-
var symbol = tagFactory("symbol",
|
|
10520
|
-
var marker = tagFactory("marker",
|
|
11055
|
+
var circle = tagFactory("circle", SVG_NS4);
|
|
11056
|
+
var ellipse = tagFactory("ellipse", SVG_NS4);
|
|
11057
|
+
var g = tagFactory("g", SVG_NS4);
|
|
11058
|
+
var line = tagFactory("line", SVG_NS4);
|
|
11059
|
+
var path = tagFactory("path", SVG_NS4);
|
|
11060
|
+
var polygon = tagFactory("polygon", SVG_NS4);
|
|
11061
|
+
var polyline = tagFactory("polyline", SVG_NS4);
|
|
11062
|
+
var rect = tagFactory("rect", SVG_NS4);
|
|
11063
|
+
var text = tagFactory("text", SVG_NS4);
|
|
11064
|
+
var tspan = tagFactory("tspan", SVG_NS4);
|
|
11065
|
+
var defs = tagFactory("defs", SVG_NS4);
|
|
11066
|
+
var clipPath = tagFactory("clipPath", SVG_NS4);
|
|
11067
|
+
var mask = tagFactory("mask", SVG_NS4);
|
|
11068
|
+
var pattern = tagFactory("pattern", SVG_NS4);
|
|
11069
|
+
var linearGradient = tagFactory("linearGradient", SVG_NS4);
|
|
11070
|
+
var radialGradient = tagFactory("radialGradient", SVG_NS4);
|
|
11071
|
+
var stop = tagFactory("stop", SVG_NS4);
|
|
11072
|
+
var use = tagFactory("use", SVG_NS4);
|
|
11073
|
+
var symbol = tagFactory("symbol", SVG_NS4);
|
|
11074
|
+
var marker = tagFactory("marker", SVG_NS4);
|
|
10521
11075
|
var center = tagFactory("center");
|
|
10522
11076
|
var font = tagFactory("font");
|
|
10523
11077
|
var marquee = tagFactory("marquee");
|
|
@@ -11393,7 +11947,7 @@ var CDN_ENTRY_POINTS = {
|
|
|
11393
11947
|
};
|
|
11394
11948
|
var packageInfo = {
|
|
11395
11949
|
name: "sibujs",
|
|
11396
|
-
version: true ? "4.
|
|
11950
|
+
version: true ? "4.8.0" : "dev",
|
|
11397
11951
|
entryPoints: MODULE_ENTRY_POINTS,
|
|
11398
11952
|
/**
|
|
11399
11953
|
* Generate the package.json `exports` map. Module entries resolve to the
|
|
@@ -11538,7 +12092,7 @@ var env = {
|
|
|
11538
12092
|
};
|
|
11539
12093
|
|
|
11540
12094
|
// src/plugins/versioning.ts
|
|
11541
|
-
var VERSION = true ? "4.
|
|
12095
|
+
var VERSION = true ? "4.8.0" : "dev";
|
|
11542
12096
|
var NUM = "(?:0|[1-9]\\d*)";
|
|
11543
12097
|
var PRE_ID = `(?:${NUM}|\\d*[a-zA-Z-][0-9a-zA-Z-]*)`;
|
|
11544
12098
|
var BUILD_ID = "[0-9a-zA-Z-]+";
|
|
@@ -11821,12 +12375,14 @@ function extractRangeTarget(range) {
|
|
|
11821
12375
|
function preloadCritical(resources) {
|
|
11822
12376
|
if (typeof document === "undefined") return;
|
|
11823
12377
|
for (const resource2 of resources) {
|
|
11824
|
-
const
|
|
12378
|
+
const href = sanitizeUrl(resource2.href);
|
|
12379
|
+
if (!href) continue;
|
|
12380
|
+
const safeHref = typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(href) : href.replace(/["\\]/g, "\\$&");
|
|
11825
12381
|
const existing = document.querySelector(`link[rel="preload"][href="${safeHref}"]`);
|
|
11826
12382
|
if (existing) continue;
|
|
11827
12383
|
const link2 = document.createElement("link");
|
|
11828
12384
|
link2.rel = "preload";
|
|
11829
|
-
link2.href =
|
|
12385
|
+
link2.href = href;
|
|
11830
12386
|
link2.setAttribute("as", resource2.as);
|
|
11831
12387
|
if (resource2.type) {
|
|
11832
12388
|
link2.type = resource2.type;
|
|
@@ -14830,7 +15386,7 @@ var _themeLayers = globalSingleton(
|
|
|
14830
15386
|
function commitThemeProperty(root, name, record) {
|
|
14831
15387
|
const top = record.layers[record.layers.length - 1];
|
|
14832
15388
|
if (top) {
|
|
14833
|
-
root.style.setProperty(name, top.value);
|
|
15389
|
+
root.style.setProperty(name, sanitizeCSSDeclaration(name, String(top.value), { element: root }));
|
|
14834
15390
|
return;
|
|
14835
15391
|
}
|
|
14836
15392
|
_themeLayers.get(root)?.delete(name);
|