sibujs 4.0.1 → 4.2.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 +29 -1
- package/dist/browser.cjs +21 -22
- package/dist/browser.js +6 -6
- package/dist/build.cjs +363 -110
- package/dist/build.js +15 -15
- package/dist/cdn.dev.global.js +398 -0
- package/dist/cdn.global.js +10 -10
- package/dist/{chunk-AD5YSZAN.js → chunk-2LOYNGBY.js} +2 -2
- package/dist/{chunk-VPP2FONR.js → chunk-2WLZ6757.js} +17 -10
- package/dist/{chunk-UNAYBND2.js → chunk-3VTSPNC5.js} +2 -2
- package/dist/{chunk-TIRZCERI.js → chunk-5DXA2J44.js} +1 -1
- package/dist/{chunk-QD4I7ZGZ.js → chunk-6ZGI3RBE.js} +149 -33
- package/dist/{chunk-JYXQCELN.js → chunk-7ALC7KGE.js} +13 -7
- package/dist/{chunk-XDOMTQHM.js → chunk-7VEC3UD2.js} +3 -3
- package/dist/{chunk-PTLJ7NQX.js → chunk-BMYYZWHX.js} +3 -3
- package/dist/{chunk-PHB3MCK4.js → chunk-BNKV4REK.js} +7 -8
- package/dist/{chunk-XET2RUJF.js → chunk-FOWBJZDL.js} +7 -8
- package/dist/{chunk-5BVKQX2F.js → chunk-GDUNQCCW.js} +4 -4
- package/dist/{chunk-TVURNWDK.js → chunk-HECVW343.js} +20 -9
- package/dist/{chunk-PHRH66Y7.js → chunk-HJEPKZ2O.js} +7 -8
- package/dist/{chunk-PJDSI2K7.js → chunk-HZEBO22J.js} +125 -42
- package/dist/{chunk-5INI7D2L.js → chunk-IXKSNWV5.js} +74 -11
- package/dist/{chunk-IKVUUE7D.js → chunk-KE4KWRDY.js} +3 -3
- package/dist/{chunk-AW6HPJ3L.js → chunk-KKLW7YWL.js} +1 -1
- package/dist/{chunk-XZMCVZW6.js → chunk-NEYWS4EX.js} +6 -6
- package/dist/{chunk-HYCCIYNS.js → chunk-NIOYEGBQ.js} +13 -14
- package/dist/{chunk-YLV26GAJ.js → chunk-OUWAIXIK.js} +3 -3
- package/dist/{chunk-E72G5JSK.js → chunk-P3DHXBR6.js} +1 -1
- package/dist/{chunk-J4WZMCIW.js → chunk-QCFLDD7C.js} +5 -5
- package/dist/{chunk-DHDZ7IVN.js → chunk-QKRPLZ2V.js} +7 -8
- package/dist/{chunk-52ERIVFD.js → chunk-QL4UREZO.js} +6 -6
- package/dist/{chunk-TNEHT3NG.js → chunk-SF3TB4K6.js} +8 -8
- package/dist/{chunk-HPXTUPJD.js → chunk-XZ2N525U.js} +6 -6
- package/dist/{customElement-CKLoO63w.d.ts → customElement-CNZxEB9G.d.cts} +77 -0
- package/dist/{customElement-CKLoO63w.d.cts → customElement-CNZxEB9G.d.ts} +77 -0
- package/dist/data.cjs +23 -25
- package/dist/data.js +9 -9
- package/dist/devtools.cjs +26 -23
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +8 -8
- package/dist/{dispose-4FZ6OFXR.js → dispose-46BOMMQJ.js} +2 -2
- package/dist/ecosystem.cjs +230 -68
- package/dist/ecosystem.js +11 -11
- package/dist/extras.cjs +251 -87
- package/dist/extras.d.cts +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/extras.js +25 -25
- package/dist/index.cjs +358 -104
- package/dist/index.d.cts +287 -34
- package/dist/index.d.ts +287 -34
- package/dist/index.js +17 -15
- package/dist/{introspect-RjLfIFpL.d.cts → introspect-D5xF-0Es.d.cts} +7 -0
- package/dist/{introspect-DOZfmC-4.d.ts → introspect-rSBIxEQi.d.ts} +7 -0
- package/dist/motion.cjs +21 -23
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +24 -25
- package/dist/patterns.d.cts +8 -0
- package/dist/patterns.d.ts +8 -0
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +24 -28
- package/dist/performance.js +9 -9
- package/dist/plugins.cjs +268 -87
- package/dist/plugins.d.cts +92 -0
- package/dist/plugins.d.ts +92 -0
- package/dist/plugins.js +18 -17
- package/dist/{ssr-JFP5535P.js → ssr-Y7XOEPEN.js} +5 -5
- package/dist/ssr.cjs +241 -80
- package/dist/ssr.js +12 -12
- package/dist/testing.cjs +19 -20
- package/dist/testing.js +5 -5
- package/dist/ui.cjs +106 -44
- package/dist/ui.d.cts +7 -1
- package/dist/ui.d.ts +7 -1
- package/dist/ui.js +10 -10
- package/dist/widgets.cjs +21 -22
- package/dist/widgets.d.cts +8 -0
- package/dist/widgets.d.ts +8 -0
- package/dist/widgets.js +9 -9
- package/package.json +11 -2
package/dist/extras.cjs
CHANGED
|
@@ -318,23 +318,28 @@ __export(extras_exports, {
|
|
|
318
318
|
module.exports = __toCommonJS(extras_exports);
|
|
319
319
|
|
|
320
320
|
// src/core/dev.ts
|
|
321
|
+
var DEV = typeof __SIBU_DEV__ !== "undefined" ? !!__SIBU_DEV__ : typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
|
|
322
|
+
// safe default: off in browser, on in test/dev Node
|
|
323
|
+
typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
324
|
+
);
|
|
321
325
|
function isDev() {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
// this branch is unreachable here.
|
|
326
|
-
/* v8 ignore next 2 */
|
|
327
|
-
typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
328
|
-
);
|
|
326
|
+
if (typeof globalThis.__SIBU_DEV__ !== "undefined") return !!globalThis.__SIBU_DEV__;
|
|
327
|
+
if (typeof __SIBU_DEV__ !== "undefined") return !!__SIBU_DEV__;
|
|
328
|
+
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
329
329
|
}
|
|
330
|
-
var _isDev = isDev();
|
|
331
330
|
function devAssert(condition, message) {
|
|
332
|
-
if (
|
|
331
|
+
if ((typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) && !condition) {
|
|
333
332
|
throw new Error(`[SibuJS] ${message}`);
|
|
334
333
|
}
|
|
335
334
|
}
|
|
335
|
+
function devWarnLazy(build) {
|
|
336
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
337
|
+
const message = build();
|
|
338
|
+
if (message) console.warn(`[SibuJS] ${message}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
336
341
|
function devWarn(message) {
|
|
337
|
-
if (
|
|
342
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
338
343
|
console.warn(`[SibuJS] ${message}`);
|
|
339
344
|
}
|
|
340
345
|
}
|
|
@@ -645,7 +650,14 @@ function reactiveBinding(commit, ownerNode) {
|
|
|
645
650
|
subscriber._disposed = false;
|
|
646
651
|
subscriber._errorPhase = "binding";
|
|
647
652
|
subscriber._errorNode = ownerNode;
|
|
648
|
-
|
|
653
|
+
try {
|
|
654
|
+
run();
|
|
655
|
+
} catch (err) {
|
|
656
|
+
subscriber._disposed = true;
|
|
657
|
+
subscriber._errorNode = void 0;
|
|
658
|
+
cleanup(subscriber);
|
|
659
|
+
throw err;
|
|
660
|
+
}
|
|
649
661
|
return subscriber._dispose ?? (subscriber._dispose = () => {
|
|
650
662
|
subscriber._disposed = true;
|
|
651
663
|
subscriber._errorNode = void 0;
|
|
@@ -876,17 +888,16 @@ function forEachSubscriber(signal2, visit) {
|
|
|
876
888
|
}
|
|
877
889
|
|
|
878
890
|
// src/reactivity/track.ts
|
|
879
|
-
var
|
|
880
|
-
var _runtimeVersion = true ? "4.0.1" : "dev";
|
|
891
|
+
var _runtimeVersion = true ? "4.2.0" : "dev";
|
|
881
892
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
882
893
|
function resolveReactiveApi() {
|
|
883
894
|
const g2 = globalThis;
|
|
884
895
|
const existing = g2[REGISTRY_KEY];
|
|
885
896
|
if (existing) {
|
|
886
|
-
if (
|
|
897
|
+
if (DEV && !existing.__dupWarned) {
|
|
887
898
|
existing.__dupWarned = true;
|
|
888
899
|
devWarn(
|
|
889
|
-
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity
|
|
900
|
+
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity is NOT broken and no bundler configuration is required: every copy routes through the first one via a global registry, so signal writes still reach subscribers registered by any copy. This is only a SIZE issue \u2014 the duplicate copy's bytes are downloaded and parsed for nothing. If you want them back, de-duplicate sibujs in your bundler (Vite: resolve.dedupe: ['sibujs']). Mismatched VERSIONS above are worth fixing regardless, since only the first one loaded is used.`
|
|
890
901
|
);
|
|
891
902
|
}
|
|
892
903
|
return existing;
|
|
@@ -1232,7 +1243,6 @@ var isBatching = API2.isBatching;
|
|
|
1232
1243
|
|
|
1233
1244
|
// src/core/signals/signal.ts
|
|
1234
1245
|
var _g2 = globalThis;
|
|
1235
|
-
var _isDev3 = isDev();
|
|
1236
1246
|
function signal(initial, options) {
|
|
1237
1247
|
const state2 = {
|
|
1238
1248
|
value: initial,
|
|
@@ -1245,7 +1255,7 @@ function signal(initial, options) {
|
|
|
1245
1255
|
_d: false,
|
|
1246
1256
|
_validate: void 0
|
|
1247
1257
|
};
|
|
1248
|
-
const debugName =
|
|
1258
|
+
const debugName = DEV ? options?.name : void 0;
|
|
1249
1259
|
const equalsFn = options?.equals;
|
|
1250
1260
|
if (debugName) state2.__name = debugName;
|
|
1251
1261
|
function get() {
|
|
@@ -1262,7 +1272,7 @@ function signal(initial, options) {
|
|
|
1262
1272
|
if (equalsFn(prev, newValue)) return;
|
|
1263
1273
|
state2.value = newValue;
|
|
1264
1274
|
state2.__v++;
|
|
1265
|
-
if (
|
|
1275
|
+
if (DEV) {
|
|
1266
1276
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1267
1277
|
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
1268
1278
|
}
|
|
@@ -1270,7 +1280,7 @@ function signal(initial, options) {
|
|
|
1270
1280
|
notifySubscribers2(state2);
|
|
1271
1281
|
}
|
|
1272
1282
|
};
|
|
1273
|
-
} else if (
|
|
1283
|
+
} else if (DEV) {
|
|
1274
1284
|
set = (next) => {
|
|
1275
1285
|
const prev = state2.value;
|
|
1276
1286
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
@@ -1295,7 +1305,7 @@ function signal(initial, options) {
|
|
|
1295
1305
|
}
|
|
1296
1306
|
};
|
|
1297
1307
|
}
|
|
1298
|
-
if (
|
|
1308
|
+
if (DEV) {
|
|
1299
1309
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1300
1310
|
if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
1301
1311
|
}
|
|
@@ -2432,11 +2442,10 @@ function syncAdapter(config) {
|
|
|
2432
2442
|
}
|
|
2433
2443
|
|
|
2434
2444
|
// src/core/rendering/context.ts
|
|
2435
|
-
var _isDev4 = isDev();
|
|
2436
2445
|
function context(defaultValue) {
|
|
2437
2446
|
const [getValue, setValue] = signal(defaultValue);
|
|
2438
2447
|
const warnIfSSR = (method) => {
|
|
2439
|
-
if (!
|
|
2448
|
+
if (!DEV || !isSSR()) return;
|
|
2440
2449
|
devWarn(
|
|
2441
2450
|
`context.${method}() called during SSR. SibuJS context() is application-global \u2014 it is NOT isolated per request, so a concurrent request can observe this value. Do not use context() for request-specific SSR data; pass it explicitly or use request-scoped storage instead.`
|
|
2442
2451
|
);
|
|
@@ -2464,7 +2473,7 @@ function context(defaultValue) {
|
|
|
2464
2473
|
setValue(value);
|
|
2465
2474
|
try {
|
|
2466
2475
|
const result = fn();
|
|
2467
|
-
if (
|
|
2476
|
+
if (DEV && result !== null && typeof result?.then === "function") {
|
|
2468
2477
|
devWarn(
|
|
2469
2478
|
"context.withContext() received an async callback. Scoping is synchronous only \u2014 the previous value is restored as soon as the callback returns its promise, so anything after an `await` runs outside the scope."
|
|
2470
2479
|
);
|
|
@@ -2717,20 +2726,75 @@ function decodeCssEscapes(value) {
|
|
|
2717
2726
|
}
|
|
2718
2727
|
return out;
|
|
2719
2728
|
}
|
|
2720
|
-
|
|
2721
|
-
|
|
2729
|
+
var BLOCKED_CSS_NEEDLES = [
|
|
2730
|
+
"url(",
|
|
2731
|
+
"expression(",
|
|
2732
|
+
"javascript:",
|
|
2733
|
+
"vbscript:",
|
|
2734
|
+
"-moz-binding",
|
|
2735
|
+
"behavior:",
|
|
2736
|
+
"@import",
|
|
2737
|
+
"image-set(",
|
|
2738
|
+
"filter:progid"
|
|
2739
|
+
];
|
|
2740
|
+
function describeElement(el) {
|
|
2741
|
+
if (!el) return "an element";
|
|
2742
|
+
let out = el.tagName.toLowerCase();
|
|
2743
|
+
const id = el.getAttribute("id");
|
|
2744
|
+
if (id) out += `#${id}`;
|
|
2745
|
+
const cls = el.getAttribute("class");
|
|
2746
|
+
if (cls) out += `.${cls.trim().split(/\s+/).slice(0, 3).join(".")}`;
|
|
2747
|
+
return `<${out}>`;
|
|
2748
|
+
}
|
|
2749
|
+
var warnedDeclarations = /* @__PURE__ */ new Set();
|
|
2750
|
+
var MAX_WARNED_DECLARATIONS = 100;
|
|
2751
|
+
var declarationCapAnnounced = false;
|
|
2752
|
+
function warnDroppedDeclaration(value, reason, ctx) {
|
|
2753
|
+
devWarnLazy(() => {
|
|
2754
|
+
const reasons = [
|
|
2755
|
+
"url() in an inline style is an exfiltration channel: the browser fetches it immediately and the URL's path or query can carry page data off-origin",
|
|
2756
|
+
"expression() executes arbitrary script in legacy engines",
|
|
2757
|
+
"the javascript: scheme executes script",
|
|
2758
|
+
"the vbscript: scheme executes script",
|
|
2759
|
+
"-moz-binding loads and runs remote XBL",
|
|
2760
|
+
"behavior: loads and runs a remote HTC script",
|
|
2761
|
+
"@import pulls in a remote stylesheet",
|
|
2762
|
+
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
2763
|
+
"filter:progid activates legacy scriptable filters"
|
|
2764
|
+
];
|
|
2765
|
+
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
2766
|
+
const where = describeElement(ctx?.element);
|
|
2767
|
+
const key = `${where}|${declaration}`;
|
|
2768
|
+
if (warnedDeclarations.has(key)) return "";
|
|
2769
|
+
if (warnedDeclarations.size >= MAX_WARNED_DECLARATIONS) {
|
|
2770
|
+
if (declarationCapAnnounced) return "";
|
|
2771
|
+
declarationCapAnnounced = true;
|
|
2772
|
+
return `${MAX_WARNED_DECLARATIONS} distinct dropped style declarations have been reported; suppressing further ones for the rest of this session so they cannot flood the console. The declarations are still dropped \u2014 only the reporting stops. Fix the reported ones and reload to see any that remain.`;
|
|
2773
|
+
}
|
|
2774
|
+
warnedDeclarations.add(key);
|
|
2775
|
+
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.`;
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
function blockedCssReason(value) {
|
|
2779
|
+
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
2722
2780
|
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
2723
2781
|
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
2724
|
-
|
|
2725
|
-
return
|
|
2782
|
+
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
2783
|
+
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
2726
2784
|
}
|
|
2727
|
-
return
|
|
2785
|
+
return -1;
|
|
2728
2786
|
}
|
|
2729
|
-
function
|
|
2787
|
+
function sanitizeCSSValue(value, context2) {
|
|
2788
|
+
const reason = blockedCssReason(value);
|
|
2789
|
+
if (reason === -1) return value;
|
|
2790
|
+
warnDroppedDeclaration(value, reason, context2);
|
|
2791
|
+
return "";
|
|
2792
|
+
}
|
|
2793
|
+
function sanitizeStyleAttribute(cssText, context2) {
|
|
2730
2794
|
const input2 = String(cssText);
|
|
2731
2795
|
if (input2.trim() === "") return "";
|
|
2732
2796
|
if (typeof document === "undefined") {
|
|
2733
|
-
return sanitizeCSSValue(input2) === "" ? "" : input2;
|
|
2797
|
+
return sanitizeCSSValue(input2, context2) === "" ? "" : input2;
|
|
2734
2798
|
}
|
|
2735
2799
|
const probe = document.createElement("div");
|
|
2736
2800
|
try {
|
|
@@ -2742,8 +2806,12 @@ function sanitizeStyleAttribute(cssText) {
|
|
|
2742
2806
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
2743
2807
|
const property = probe.style[i2];
|
|
2744
2808
|
const value = probe.style.getPropertyValue(property);
|
|
2745
|
-
|
|
2746
|
-
if (
|
|
2809
|
+
let reason = blockedCssReason(value);
|
|
2810
|
+
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
2811
|
+
if (reason !== -1) {
|
|
2812
|
+
warnDroppedDeclaration(value, reason, { property, element: context2?.element });
|
|
2813
|
+
continue;
|
|
2814
|
+
}
|
|
2747
2815
|
const priority = probe.style.getPropertyPriority(property);
|
|
2748
2816
|
declarations.push(`${property}: ${value}${priority ? ` !${priority}` : ""}`);
|
|
2749
2817
|
}
|
|
@@ -2791,11 +2859,11 @@ function isPolicyAttribute(name) {
|
|
|
2791
2859
|
const lower = name.toLowerCase();
|
|
2792
2860
|
return lower === "style" || URL_ATTRIBUTES.has(lower);
|
|
2793
2861
|
}
|
|
2794
|
-
function sanitizeAttributeString(attr, value) {
|
|
2862
|
+
function sanitizeAttributeString(attr, value, context2) {
|
|
2795
2863
|
const lower = attr.toLowerCase();
|
|
2796
2864
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
2797
2865
|
if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
|
|
2798
|
-
if (lower === "style") return sanitizeStyleAttribute(value);
|
|
2866
|
+
if (lower === "style") return sanitizeStyleAttribute(value, context2);
|
|
2799
2867
|
return value;
|
|
2800
2868
|
}
|
|
2801
2869
|
|
|
@@ -5111,7 +5179,6 @@ function reportDrainRunaway(label2, executed, remaining) {
|
|
|
5111
5179
|
{ executed, remaining }
|
|
5112
5180
|
);
|
|
5113
5181
|
}
|
|
5114
|
-
var _isDev5 = isDev();
|
|
5115
5182
|
var activeBindingCount = 0;
|
|
5116
5183
|
function registerDisposer(node, teardown) {
|
|
5117
5184
|
let disposers = elementDisposers.get(node);
|
|
@@ -5120,7 +5187,7 @@ function registerDisposer(node, teardown) {
|
|
|
5120
5187
|
elementDisposers.set(node, disposers);
|
|
5121
5188
|
}
|
|
5122
5189
|
disposers.push(teardown);
|
|
5123
|
-
if (
|
|
5190
|
+
if (DEV) activeBindingCount++;
|
|
5124
5191
|
}
|
|
5125
5192
|
function dispose(node) {
|
|
5126
5193
|
const stack = [node];
|
|
@@ -5143,13 +5210,13 @@ function dispose(node) {
|
|
|
5143
5210
|
if (!pending || pending.length === 0) break;
|
|
5144
5211
|
const snapshot = pending.slice();
|
|
5145
5212
|
elementDisposers.delete(current);
|
|
5146
|
-
if (
|
|
5213
|
+
if (DEV) activeBindingCount -= snapshot.length;
|
|
5147
5214
|
for (let i3 = 0; i3 < snapshot.length; i3++) {
|
|
5148
5215
|
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
5149
5216
|
const rest = snapshot.slice(i3);
|
|
5150
5217
|
const added = elementDisposers.get(current);
|
|
5151
5218
|
elementDisposers.set(current, added ? rest.concat(added) : rest);
|
|
5152
|
-
if (
|
|
5219
|
+
if (DEV) activeBindingCount += rest.length;
|
|
5153
5220
|
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
5154
5221
|
runaway = true;
|
|
5155
5222
|
break;
|
|
@@ -6266,16 +6333,16 @@ function sanitizeCSS(css) {
|
|
|
6266
6333
|
function firstCompoundEnd(selector) {
|
|
6267
6334
|
let parens = 0;
|
|
6268
6335
|
let brackets = 0;
|
|
6269
|
-
let
|
|
6336
|
+
let quote2 = null;
|
|
6270
6337
|
for (let i2 = 0; i2 < selector.length; i2++) {
|
|
6271
6338
|
const ch = selector[i2];
|
|
6272
|
-
if (
|
|
6339
|
+
if (quote2) {
|
|
6273
6340
|
if (ch === "\\") i2++;
|
|
6274
|
-
else if (ch ===
|
|
6341
|
+
else if (ch === quote2) quote2 = null;
|
|
6275
6342
|
continue;
|
|
6276
6343
|
}
|
|
6277
6344
|
if (ch === '"' || ch === "'") {
|
|
6278
|
-
|
|
6345
|
+
quote2 = ch;
|
|
6279
6346
|
continue;
|
|
6280
6347
|
}
|
|
6281
6348
|
if (ch === "\\") {
|
|
@@ -6451,7 +6518,6 @@ function removeScopedStyle(scopeId) {
|
|
|
6451
6518
|
}
|
|
6452
6519
|
|
|
6453
6520
|
// src/utils/setSafeAttribute.ts
|
|
6454
|
-
var _isDev6 = isDev();
|
|
6455
6521
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
6456
6522
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
6457
6523
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
@@ -6474,7 +6540,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
6474
6540
|
const ns = namespaceFor(el, name);
|
|
6475
6541
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
6476
6542
|
if (isEventHandlerAttr(name)) {
|
|
6477
|
-
if (
|
|
6543
|
+
if (DEV) {
|
|
6478
6544
|
devWarn(
|
|
6479
6545
|
`${options.label ?? "setSafeAttribute"}: refusing to set event-handler attribute "${name}". Its value would be evaluated as JavaScript. Use on:{ ${name.slice(2)}: fn } instead.`
|
|
6480
6546
|
);
|
|
@@ -6489,7 +6555,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
6489
6555
|
return true;
|
|
6490
6556
|
}
|
|
6491
6557
|
if (isHtmlContentAttribute(name)) {
|
|
6492
|
-
if (
|
|
6558
|
+
if (DEV) {
|
|
6493
6559
|
devWarn(
|
|
6494
6560
|
`${options.label ?? "setSafeAttribute"}: refusing to set "${name}". The browser parses this attribute as a nested HTML document, so a generic string value cannot be made safe \u2014 attribute escaping is undone before the parse. Build the frame's content another way.`
|
|
6495
6561
|
);
|
|
@@ -6518,7 +6584,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
6518
6584
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
6519
6585
|
return true;
|
|
6520
6586
|
}
|
|
6521
|
-
const safe = sanitizeAttributeString(name, str);
|
|
6587
|
+
const safe = sanitizeAttributeString(name, str, { element: el });
|
|
6522
6588
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
6523
6589
|
if (current === safe) return true;
|
|
6524
6590
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -7090,7 +7156,6 @@ function uniqueId(suffix) {
|
|
|
7090
7156
|
}
|
|
7091
7157
|
|
|
7092
7158
|
// src/performance/domRecycler.ts
|
|
7093
|
-
var _isDev7 = isDev();
|
|
7094
7159
|
var DOMPool = class {
|
|
7095
7160
|
constructor(maxSize = 50) {
|
|
7096
7161
|
this.pools = /* @__PURE__ */ new Map();
|
|
@@ -7117,7 +7182,7 @@ var DOMPool = class {
|
|
|
7117
7182
|
* is almost certainly a bug.
|
|
7118
7183
|
*/
|
|
7119
7184
|
release(element) {
|
|
7120
|
-
if (
|
|
7185
|
+
if (DEV && element.isConnected) {
|
|
7121
7186
|
devWarn(
|
|
7122
7187
|
"DOMPool.release() called on a still-connected element. Detach it from the DOM first (remove() / dispose())."
|
|
7123
7188
|
);
|
|
@@ -7262,9 +7327,9 @@ function parseMetaRefreshContent(content) {
|
|
|
7262
7327
|
i2++;
|
|
7263
7328
|
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
7264
7329
|
let destination;
|
|
7265
|
-
const
|
|
7266
|
-
if (
|
|
7267
|
-
const close = raw.indexOf(
|
|
7330
|
+
const quote2 = raw[i2];
|
|
7331
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
7332
|
+
const close = raw.indexOf(quote2, i2 + 1);
|
|
7268
7333
|
if (close === -1) return forbidden("unterminated quoted destination");
|
|
7269
7334
|
destination = raw.slice(i2 + 1, close);
|
|
7270
7335
|
const rest = trimAsciiWhitespace(raw.slice(close + 1));
|
|
@@ -7395,13 +7460,12 @@ function isForbiddenSsrAttr(lowerName) {
|
|
|
7395
7460
|
function sanitizeSsrAttributeValue(lowerName, value) {
|
|
7396
7461
|
return sanitizeAttributeString(lowerName, value);
|
|
7397
7462
|
}
|
|
7398
|
-
var _isDev8 = isDev();
|
|
7399
7463
|
var SAFE_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
7400
7464
|
function isSafeAttrName(name) {
|
|
7401
7465
|
return SAFE_ATTR_NAME.test(name);
|
|
7402
7466
|
}
|
|
7403
7467
|
function ssrErrorComment(err) {
|
|
7404
|
-
if (
|
|
7468
|
+
if (DEV) {
|
|
7405
7469
|
const msg = escapeHtml(err instanceof Error ? err.message : String(err));
|
|
7406
7470
|
return `<!--SSR error: ${safeCommentText(msg)}-->`;
|
|
7407
7471
|
}
|
|
@@ -7447,10 +7511,10 @@ function renderToString(element) {
|
|
|
7447
7511
|
}
|
|
7448
7512
|
const tag = element.tagName.toLowerCase();
|
|
7449
7513
|
if (tag === "script" || tag === "style") {
|
|
7450
|
-
return
|
|
7514
|
+
return DEV ? `<!--ssr:${tag}-stripped-->` : "";
|
|
7451
7515
|
}
|
|
7452
7516
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
7453
|
-
return
|
|
7517
|
+
return DEV ? "<!--ssr:invalid-tag-->" : "";
|
|
7454
7518
|
}
|
|
7455
7519
|
let html2 = `<${tag}`;
|
|
7456
7520
|
for (const attr of Array.from(element.attributes)) {
|
|
@@ -7492,7 +7556,7 @@ function hydrate(component, container, options = {}) {
|
|
|
7492
7556
|
const first = mismatches[0];
|
|
7493
7557
|
if (options.onMismatch) {
|
|
7494
7558
|
options.onMismatch(first);
|
|
7495
|
-
} else if (
|
|
7559
|
+
} else if (DEV) {
|
|
7496
7560
|
console.warn(
|
|
7497
7561
|
`[SibuJS hydration] ${first.message}
|
|
7498
7562
|
at ${first.path}
|
|
@@ -7693,11 +7757,11 @@ async function* renderToStream(element) {
|
|
|
7693
7757
|
}
|
|
7694
7758
|
const tag = element.tagName.toLowerCase();
|
|
7695
7759
|
if (tag === "script" || tag === "style") {
|
|
7696
|
-
if (
|
|
7760
|
+
if (DEV) yield `<!--ssr:${tag}-stripped-->`;
|
|
7697
7761
|
return;
|
|
7698
7762
|
}
|
|
7699
7763
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
7700
|
-
if (
|
|
7764
|
+
if (DEV) yield "<!--ssr:invalid-tag-->";
|
|
7701
7765
|
return;
|
|
7702
7766
|
}
|
|
7703
7767
|
let openTag = `<${tag}`;
|
|
@@ -7840,7 +7904,7 @@ function ssrSuspense(props) {
|
|
|
7840
7904
|
},
|
|
7841
7905
|
(err) => {
|
|
7842
7906
|
if (timer) clearTimeout(timer);
|
|
7843
|
-
if (
|
|
7907
|
+
if (DEV) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
|
|
7844
7908
|
return { id, html: fallbackHtml };
|
|
7845
7909
|
}
|
|
7846
7910
|
);
|
|
@@ -7886,7 +7950,7 @@ function serializeState(state2, nonce, options) {
|
|
|
7886
7950
|
}
|
|
7887
7951
|
function deserializeState(validate) {
|
|
7888
7952
|
if (typeof window === "undefined") return void 0;
|
|
7889
|
-
if (
|
|
7953
|
+
if (DEV && !validate) {
|
|
7890
7954
|
console.warn(
|
|
7891
7955
|
"[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
|
|
7892
7956
|
);
|
|
@@ -8906,8 +8970,101 @@ function isWasmCached(key) {
|
|
|
8906
8970
|
return moduleCache.has(key);
|
|
8907
8971
|
}
|
|
8908
8972
|
|
|
8973
|
+
// src/core/rendering/focusPreservation.ts
|
|
8974
|
+
var IDENTITY_ATTRS = ["data-focus-key", "id", "name"];
|
|
8975
|
+
var SELECTABLE_TYPES = /* @__PURE__ */ new Set(["text", "search", "url", "tel", "password", ""]);
|
|
8976
|
+
function selectionOf(el) {
|
|
8977
|
+
const tag = el.tagName;
|
|
8978
|
+
const selectable = tag === "TEXTAREA" || tag === "INPUT" && SELECTABLE_TYPES.has(el.type.toLowerCase());
|
|
8979
|
+
if (!selectable) return { start: null, end: null, direction: null };
|
|
8980
|
+
const field = el;
|
|
8981
|
+
return { start: field.selectionStart, end: field.selectionEnd, direction: field.selectionDirection };
|
|
8982
|
+
}
|
|
8983
|
+
function captureFocusWithin(nodes) {
|
|
8984
|
+
if (nodes.length === 0 || typeof document === "undefined") return null;
|
|
8985
|
+
const active = document.activeElement;
|
|
8986
|
+
if (!active || active === document.body) return null;
|
|
8987
|
+
let inside = false;
|
|
8988
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
8989
|
+
const n = nodes[i2];
|
|
8990
|
+
if (n === active || n.nodeType === 1 && n.contains(active)) {
|
|
8991
|
+
inside = true;
|
|
8992
|
+
break;
|
|
8993
|
+
}
|
|
8994
|
+
}
|
|
8995
|
+
if (!inside) return null;
|
|
8996
|
+
let attr = null;
|
|
8997
|
+
let value = null;
|
|
8998
|
+
for (let i2 = 0; i2 < IDENTITY_ATTRS.length; i2++) {
|
|
8999
|
+
const candidate = active.getAttribute(IDENTITY_ATTRS[i2]);
|
|
9000
|
+
if (candidate) {
|
|
9001
|
+
attr = IDENTITY_ATTRS[i2];
|
|
9002
|
+
value = candidate;
|
|
9003
|
+
break;
|
|
9004
|
+
}
|
|
9005
|
+
}
|
|
9006
|
+
return { el: active, attr, value, tag: active.tagName, ...selectionOf(active) };
|
|
9007
|
+
}
|
|
9008
|
+
function quote(value) {
|
|
9009
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
9010
|
+
}
|
|
9011
|
+
function findUniqueByIdentity(nodes, selector) {
|
|
9012
|
+
let el = null;
|
|
9013
|
+
let count = 0;
|
|
9014
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
9015
|
+
const n = nodes[i2];
|
|
9016
|
+
if (n.nodeType !== 1) continue;
|
|
9017
|
+
const root = n;
|
|
9018
|
+
if (root.matches(selector)) {
|
|
9019
|
+
count++;
|
|
9020
|
+
el ?? (el = root);
|
|
9021
|
+
}
|
|
9022
|
+
const inner = root.querySelectorAll(selector);
|
|
9023
|
+
for (let j = 0; j < inner.length; j++) {
|
|
9024
|
+
count++;
|
|
9025
|
+
el ?? (el = inner[j]);
|
|
9026
|
+
}
|
|
9027
|
+
if (count > 1) return { el: null, count };
|
|
9028
|
+
}
|
|
9029
|
+
return count === 1 ? { el, count } : { el: null, count };
|
|
9030
|
+
}
|
|
9031
|
+
function refocus(el, snapshot) {
|
|
9032
|
+
el.focus();
|
|
9033
|
+
if (snapshot.start !== null && typeof el.setSelectionRange === "function") {
|
|
9034
|
+
const field = el;
|
|
9035
|
+
const max2 = field.value.length;
|
|
9036
|
+
const start = Math.min(snapshot.start, max2);
|
|
9037
|
+
const end = Math.min(snapshot.end ?? start, max2);
|
|
9038
|
+
field.setSelectionRange(start, end, snapshot.direction ?? "none");
|
|
9039
|
+
}
|
|
9040
|
+
}
|
|
9041
|
+
function restoreFocusWithin(snapshot, nodes, where) {
|
|
9042
|
+
if (!snapshot) return;
|
|
9043
|
+
if (typeof document === "undefined") return;
|
|
9044
|
+
const active = document.activeElement;
|
|
9045
|
+
if (active === snapshot.el) return;
|
|
9046
|
+
if (active && active !== document.body && active !== document.documentElement) return;
|
|
9047
|
+
if (snapshot.el.isConnected) {
|
|
9048
|
+
refocus(snapshot.el, snapshot);
|
|
9049
|
+
return;
|
|
9050
|
+
}
|
|
9051
|
+
let ambiguous = false;
|
|
9052
|
+
if (snapshot.attr && snapshot.value) {
|
|
9053
|
+
const { el: replacement, count } = findUniqueByIdentity(nodes, `[${snapshot.attr}=${quote(snapshot.value)}]`);
|
|
9054
|
+
if (replacement && replacement.tagName === snapshot.tag) {
|
|
9055
|
+
refocus(replacement, snapshot);
|
|
9056
|
+
return;
|
|
9057
|
+
}
|
|
9058
|
+
ambiguous = count > 1;
|
|
9059
|
+
}
|
|
9060
|
+
devWarnLazy(() => {
|
|
9061
|
+
const id = snapshot.attr ? ` (${snapshot.attr}="${snapshot.value}")` : "";
|
|
9062
|
+
const why = ambiguous ? `several elements in the rebuilt subtree share ${snapshot.attr}="${snapshot.value}", so there is no way to tell which one the user was in \u2014 a shared name (a radio group) identifies a GROUP, not a control. Add a unique id or data-focus-key to each` : "no element in the rebuilt subtree carries the same identity. Give it a stable id, name, or data-focus-key that the rebuild reproduces";
|
|
9063
|
+
return `${where}: a reactive rebuild discarded the focused element <${snapshot.tag.toLowerCase()}>${id} and could not re-establish it, so focus fell back to <body>. An in-progress edit ends here, and an in-progress IME composition is lost outright \u2014 a composition belongs to the DOM node, so it cannot survive the node being destroyed. ${why}, or stop the rebuild from happening: key the subtree with match(() => shapeKey(), { \u2026 }) so it is re-created only when the shape actually changes, and drive the rest with reactive attributes and text children, which mutate nodes in place instead of replacing them.`;
|
|
9064
|
+
});
|
|
9065
|
+
}
|
|
9066
|
+
|
|
8909
9067
|
// src/reactivity/bindChildNode.ts
|
|
8910
|
-
var _isDev9 = isDev();
|
|
8911
9068
|
function bindChildNode(placeholder, getter) {
|
|
8912
9069
|
let lastNodes = [];
|
|
8913
9070
|
function commit() {
|
|
@@ -8918,6 +9075,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
8918
9075
|
reportError(err, { phase: "binding", name: "bindChildNode", node: placeholder });
|
|
8919
9076
|
return;
|
|
8920
9077
|
}
|
|
9078
|
+
const focused = captureFocusWithin(lastNodes);
|
|
8921
9079
|
if (result == null || typeof result === "boolean") {
|
|
8922
9080
|
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
8923
9081
|
const node = lastNodes[i2];
|
|
@@ -8925,6 +9083,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
8925
9083
|
if (node.parentNode) node.parentNode.removeChild(node);
|
|
8926
9084
|
}
|
|
8927
9085
|
lastNodes.length = 0;
|
|
9086
|
+
restoreFocusWithin(focused, lastNodes, "bindChildNode");
|
|
8928
9087
|
return;
|
|
8929
9088
|
}
|
|
8930
9089
|
const parent = placeholder.parentNode;
|
|
@@ -8941,8 +9100,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
8941
9100
|
if (item == null || typeof item === "boolean") continue;
|
|
8942
9101
|
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
8943
9102
|
if (seen.has(node)) {
|
|
8944
|
-
if (
|
|
8945
|
-
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
9103
|
+
if (DEV) devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
8946
9104
|
continue;
|
|
8947
9105
|
}
|
|
8948
9106
|
seen.add(node);
|
|
@@ -8975,13 +9133,13 @@ function bindChildNode(placeholder, getter) {
|
|
|
8975
9133
|
prev = node;
|
|
8976
9134
|
}
|
|
8977
9135
|
lastNodes = newNodes;
|
|
9136
|
+
restoreFocusWithin(focused, newNodes, "bindChildNode");
|
|
8978
9137
|
}
|
|
8979
9138
|
return reactiveBinding2(commit, placeholder);
|
|
8980
9139
|
}
|
|
8981
9140
|
|
|
8982
9141
|
// src/core/rendering/tagFactory.ts
|
|
8983
9142
|
var SVG_NS3 = "http://www.w3.org/2000/svg";
|
|
8984
|
-
var _isDev10 = isDev();
|
|
8985
9143
|
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
8986
9144
|
function isBlockedTag(tag) {
|
|
8987
9145
|
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
@@ -8999,18 +9157,9 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
|
8999
9157
|
"self",
|
|
9000
9158
|
"frames"
|
|
9001
9159
|
]);
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
const tokens = t.split(/\s+/);
|
|
9006
|
-
let sawClassish = false;
|
|
9007
|
-
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
9008
|
-
const tok = tokens[i2];
|
|
9009
|
-
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return false;
|
|
9010
|
-
if (/[-:/0-9]/.test(tok)) sawClassish = true;
|
|
9011
|
-
}
|
|
9012
|
-
return sawClassish;
|
|
9013
|
-
}
|
|
9160
|
+
var warnedLoneStrings = /* @__PURE__ */ new Set();
|
|
9161
|
+
var MAX_WARNED_LONE_STRINGS = 100;
|
|
9162
|
+
var loneStringCapAnnounced = false;
|
|
9014
9163
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
9015
9164
|
function toKebab(prop) {
|
|
9016
9165
|
let cached = kebabCache.get(prop);
|
|
@@ -9022,13 +9171,13 @@ function toKebab(prop) {
|
|
|
9022
9171
|
function applyStyle(el, style2) {
|
|
9023
9172
|
if (typeof style2 === "function") {
|
|
9024
9173
|
const teardown = reactiveBinding2(() => {
|
|
9025
|
-
el.setAttribute("style", sanitizeStyleAttribute(String(style2())));
|
|
9174
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(style2()), { element: el }));
|
|
9026
9175
|
}, el);
|
|
9027
9176
|
registerDisposer(el, teardown);
|
|
9028
9177
|
return;
|
|
9029
9178
|
}
|
|
9030
9179
|
if (typeof style2 === "string") {
|
|
9031
|
-
el.setAttribute("style", sanitizeStyleAttribute(style2));
|
|
9180
|
+
el.setAttribute("style", sanitizeStyleAttribute(style2, { element: el }));
|
|
9032
9181
|
return;
|
|
9033
9182
|
}
|
|
9034
9183
|
const htmlEl = el;
|
|
@@ -9038,11 +9187,11 @@ function applyStyle(el, style2) {
|
|
|
9038
9187
|
if (typeof val === "function") {
|
|
9039
9188
|
const getter = val;
|
|
9040
9189
|
const teardown = reactiveBinding2(() => {
|
|
9041
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
|
|
9190
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter()), { property: name, element: el }));
|
|
9042
9191
|
}, el);
|
|
9043
9192
|
registerDisposer(el, teardown);
|
|
9044
9193
|
} else {
|
|
9045
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
|
|
9194
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val), { property: name, element: el }));
|
|
9046
9195
|
}
|
|
9047
9196
|
}
|
|
9048
9197
|
}
|
|
@@ -9149,11 +9298,26 @@ var tagFactory = (tag, ns) => {
|
|
|
9149
9298
|
appendChildren(el, second);
|
|
9150
9299
|
return el;
|
|
9151
9300
|
}
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9301
|
+
devWarnLazy(() => {
|
|
9302
|
+
const tokens = first.trim().split(/\s+/);
|
|
9303
|
+
if (tokens.length < 2) return "";
|
|
9304
|
+
let utilityTokens = 0;
|
|
9305
|
+
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
9306
|
+
const tok = tokens[i2];
|
|
9307
|
+
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return "";
|
|
9308
|
+
if (/[-:/0-9]/.test(tok)) utilityTokens++;
|
|
9309
|
+
}
|
|
9310
|
+
if (utilityTokens < 2) return "";
|
|
9311
|
+
const key = `${tag}|${first}`;
|
|
9312
|
+
if (warnedLoneStrings.has(key)) return "";
|
|
9313
|
+
if (warnedLoneStrings.size >= MAX_WARNED_LONE_STRINGS) {
|
|
9314
|
+
if (loneStringCapAnnounced) return "";
|
|
9315
|
+
loneStringCapAnnounced = true;
|
|
9316
|
+
return `tagFactory: ${MAX_WARNED_LONE_STRINGS} distinct lone-string class warnings have been reported; suppressing further ones for the rest of this session so they cannot flood the console. Fix the reported ones and reload to see any that remain.`;
|
|
9317
|
+
}
|
|
9318
|
+
warnedLoneStrings.add(key);
|
|
9319
|
+
return `tagFactory: lone string "${first}" looks like a class list but is being rendered as TEXT. For a class, use ${tag}({ class: "${first}" }) \u2014 or ${tag}("${first}", children) to set the class AND add children.`;
|
|
9320
|
+
});
|
|
9157
9321
|
el.textContent = first;
|
|
9158
9322
|
return el;
|
|
9159
9323
|
}
|
|
@@ -9170,7 +9334,7 @@ var tagFactory = (tag, ns) => {
|
|
|
9170
9334
|
if (pClass != null) applyClass(el, pClass);
|
|
9171
9335
|
const pId = props.id;
|
|
9172
9336
|
if (pId != null) {
|
|
9173
|
-
if (
|
|
9337
|
+
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
9174
9338
|
devWarn(
|
|
9175
9339
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
9176
9340
|
);
|
|
@@ -9185,7 +9349,7 @@ var tagFactory = (tag, ns) => {
|
|
|
9185
9349
|
const handler = pOn[ev];
|
|
9186
9350
|
if (typeof handler === "function") {
|
|
9187
9351
|
el.addEventListener(ev, handler);
|
|
9188
|
-
} else if (
|
|
9352
|
+
} else if (DEV) {
|
|
9189
9353
|
devWarn(
|
|
9190
9354
|
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
9191
9355
|
);
|