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/ssr.cjs
CHANGED
|
@@ -66,23 +66,23 @@ __export(ssr_exports, {
|
|
|
66
66
|
module.exports = __toCommonJS(ssr_exports);
|
|
67
67
|
|
|
68
68
|
// src/core/dev.ts
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// this branch is unreachable here.
|
|
74
|
-
/* v8 ignore next 2 */
|
|
75
|
-
typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
var _isDev = isDev();
|
|
69
|
+
var DEV = typeof __SIBU_DEV__ !== "undefined" ? !!__SIBU_DEV__ : typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
|
|
70
|
+
// safe default: off in browser, on in test/dev Node
|
|
71
|
+
typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
72
|
+
);
|
|
79
73
|
function devAssert(condition, message) {
|
|
80
|
-
if (
|
|
74
|
+
if ((typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) && !condition) {
|
|
81
75
|
throw new Error(`[SibuJS] ${message}`);
|
|
82
76
|
}
|
|
83
77
|
}
|
|
78
|
+
function devWarnLazy(build) {
|
|
79
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
80
|
+
const message = build();
|
|
81
|
+
if (message) console.warn(`[SibuJS] ${message}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
84
|
function devWarn(message) {
|
|
85
|
-
if (
|
|
85
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
86
86
|
console.warn(`[SibuJS] ${message}`);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -185,7 +185,6 @@ function reportDrainRunaway(label2, executed, remaining) {
|
|
|
185
185
|
{ executed, remaining }
|
|
186
186
|
);
|
|
187
187
|
}
|
|
188
|
-
var _isDev2 = isDev();
|
|
189
188
|
var activeBindingCount = 0;
|
|
190
189
|
function registerDisposer(node, teardown) {
|
|
191
190
|
let disposers = elementDisposers.get(node);
|
|
@@ -194,7 +193,7 @@ function registerDisposer(node, teardown) {
|
|
|
194
193
|
elementDisposers.set(node, disposers);
|
|
195
194
|
}
|
|
196
195
|
disposers.push(teardown);
|
|
197
|
-
if (
|
|
196
|
+
if (DEV) activeBindingCount++;
|
|
198
197
|
}
|
|
199
198
|
function dispose(node) {
|
|
200
199
|
const stack = [node];
|
|
@@ -217,13 +216,13 @@ function dispose(node) {
|
|
|
217
216
|
if (!pending || pending.length === 0) break;
|
|
218
217
|
const snapshot = pending.slice();
|
|
219
218
|
elementDisposers.delete(current);
|
|
220
|
-
if (
|
|
219
|
+
if (DEV) activeBindingCount -= snapshot.length;
|
|
221
220
|
for (let i3 = 0; i3 < snapshot.length; i3++) {
|
|
222
221
|
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
223
222
|
const rest = snapshot.slice(i3);
|
|
224
223
|
const added = elementDisposers.get(current);
|
|
225
224
|
elementDisposers.set(current, added ? rest.concat(added) : rest);
|
|
226
|
-
if (
|
|
225
|
+
if (DEV) activeBindingCount += rest.length;
|
|
227
226
|
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
228
227
|
runaway = true;
|
|
229
228
|
break;
|
|
@@ -386,20 +385,75 @@ function decodeCssEscapes(value) {
|
|
|
386
385
|
}
|
|
387
386
|
return out;
|
|
388
387
|
}
|
|
389
|
-
|
|
390
|
-
|
|
388
|
+
var BLOCKED_CSS_NEEDLES = [
|
|
389
|
+
"url(",
|
|
390
|
+
"expression(",
|
|
391
|
+
"javascript:",
|
|
392
|
+
"vbscript:",
|
|
393
|
+
"-moz-binding",
|
|
394
|
+
"behavior:",
|
|
395
|
+
"@import",
|
|
396
|
+
"image-set(",
|
|
397
|
+
"filter:progid"
|
|
398
|
+
];
|
|
399
|
+
function describeElement(el) {
|
|
400
|
+
if (!el) return "an element";
|
|
401
|
+
let out = el.tagName.toLowerCase();
|
|
402
|
+
const id = el.getAttribute("id");
|
|
403
|
+
if (id) out += `#${id}`;
|
|
404
|
+
const cls = el.getAttribute("class");
|
|
405
|
+
if (cls) out += `.${cls.trim().split(/\s+/).slice(0, 3).join(".")}`;
|
|
406
|
+
return `<${out}>`;
|
|
407
|
+
}
|
|
408
|
+
var warnedDeclarations = /* @__PURE__ */ new Set();
|
|
409
|
+
var MAX_WARNED_DECLARATIONS = 100;
|
|
410
|
+
var declarationCapAnnounced = false;
|
|
411
|
+
function warnDroppedDeclaration(value, reason, ctx) {
|
|
412
|
+
devWarnLazy(() => {
|
|
413
|
+
const reasons = [
|
|
414
|
+
"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",
|
|
415
|
+
"expression() executes arbitrary script in legacy engines",
|
|
416
|
+
"the javascript: scheme executes script",
|
|
417
|
+
"the vbscript: scheme executes script",
|
|
418
|
+
"-moz-binding loads and runs remote XBL",
|
|
419
|
+
"behavior: loads and runs a remote HTC script",
|
|
420
|
+
"@import pulls in a remote stylesheet",
|
|
421
|
+
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
422
|
+
"filter:progid activates legacy scriptable filters"
|
|
423
|
+
];
|
|
424
|
+
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
425
|
+
const where = describeElement(ctx?.element);
|
|
426
|
+
const key = `${where}|${declaration}`;
|
|
427
|
+
if (warnedDeclarations.has(key)) return "";
|
|
428
|
+
if (warnedDeclarations.size >= MAX_WARNED_DECLARATIONS) {
|
|
429
|
+
if (declarationCapAnnounced) return "";
|
|
430
|
+
declarationCapAnnounced = true;
|
|
431
|
+
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.`;
|
|
432
|
+
}
|
|
433
|
+
warnedDeclarations.add(key);
|
|
434
|
+
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.`;
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
function blockedCssReason(value) {
|
|
438
|
+
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
391
439
|
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
392
440
|
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
393
|
-
|
|
394
|
-
return
|
|
441
|
+
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
442
|
+
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
395
443
|
}
|
|
396
|
-
return
|
|
444
|
+
return -1;
|
|
445
|
+
}
|
|
446
|
+
function sanitizeCSSValue(value, context) {
|
|
447
|
+
const reason = blockedCssReason(value);
|
|
448
|
+
if (reason === -1) return value;
|
|
449
|
+
warnDroppedDeclaration(value, reason, context);
|
|
450
|
+
return "";
|
|
397
451
|
}
|
|
398
|
-
function sanitizeStyleAttribute(cssText) {
|
|
452
|
+
function sanitizeStyleAttribute(cssText, context) {
|
|
399
453
|
const input2 = String(cssText);
|
|
400
454
|
if (input2.trim() === "") return "";
|
|
401
455
|
if (typeof document === "undefined") {
|
|
402
|
-
return sanitizeCSSValue(input2) === "" ? "" : input2;
|
|
456
|
+
return sanitizeCSSValue(input2, context) === "" ? "" : input2;
|
|
403
457
|
}
|
|
404
458
|
const probe = document.createElement("div");
|
|
405
459
|
try {
|
|
@@ -411,8 +465,12 @@ function sanitizeStyleAttribute(cssText) {
|
|
|
411
465
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
412
466
|
const property = probe.style[i2];
|
|
413
467
|
const value = probe.style.getPropertyValue(property);
|
|
414
|
-
|
|
415
|
-
if (
|
|
468
|
+
let reason = blockedCssReason(value);
|
|
469
|
+
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
470
|
+
if (reason !== -1) {
|
|
471
|
+
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
416
474
|
const priority = probe.style.getPropertyPriority(property);
|
|
417
475
|
declarations.push(`${property}: ${value}${priority ? ` !${priority}` : ""}`);
|
|
418
476
|
}
|
|
@@ -444,11 +502,11 @@ function isPolicyAttribute(name) {
|
|
|
444
502
|
const lower = name.toLowerCase();
|
|
445
503
|
return lower === "style" || URL_ATTRIBUTES.has(lower);
|
|
446
504
|
}
|
|
447
|
-
function sanitizeAttributeString(attr, value) {
|
|
505
|
+
function sanitizeAttributeString(attr, value, context) {
|
|
448
506
|
const lower = attr.toLowerCase();
|
|
449
507
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
450
508
|
if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
|
|
451
|
-
if (lower === "style") return sanitizeStyleAttribute(value);
|
|
509
|
+
if (lower === "style") return sanitizeStyleAttribute(value, context);
|
|
452
510
|
return value;
|
|
453
511
|
}
|
|
454
512
|
|
|
@@ -486,9 +544,9 @@ function parseMetaRefreshContent(content) {
|
|
|
486
544
|
i2++;
|
|
487
545
|
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
488
546
|
let destination;
|
|
489
|
-
const
|
|
490
|
-
if (
|
|
491
|
-
const close = raw.indexOf(
|
|
547
|
+
const quote2 = raw[i2];
|
|
548
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
549
|
+
const close = raw.indexOf(quote2, i2 + 1);
|
|
492
550
|
if (close === -1) return forbidden("unterminated quoted destination");
|
|
493
551
|
destination = raw.slice(i2 + 1, close);
|
|
494
552
|
const rest = trimAsciiWhitespace(raw.slice(close + 1));
|
|
@@ -619,13 +677,12 @@ function isForbiddenSsrAttr(lowerName) {
|
|
|
619
677
|
function sanitizeSsrAttributeValue(lowerName, value) {
|
|
620
678
|
return sanitizeAttributeString(lowerName, value);
|
|
621
679
|
}
|
|
622
|
-
var _isDev3 = isDev();
|
|
623
680
|
var SAFE_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
624
681
|
function isSafeAttrName(name) {
|
|
625
682
|
return SAFE_ATTR_NAME.test(name);
|
|
626
683
|
}
|
|
627
684
|
function ssrErrorComment(err) {
|
|
628
|
-
if (
|
|
685
|
+
if (DEV) {
|
|
629
686
|
const msg = escapeHtml(err instanceof Error ? err.message : String(err));
|
|
630
687
|
return `<!--SSR error: ${safeCommentText(msg)}-->`;
|
|
631
688
|
}
|
|
@@ -671,10 +728,10 @@ function renderToString(element) {
|
|
|
671
728
|
}
|
|
672
729
|
const tag = element.tagName.toLowerCase();
|
|
673
730
|
if (tag === "script" || tag === "style") {
|
|
674
|
-
return
|
|
731
|
+
return DEV ? `<!--ssr:${tag}-stripped-->` : "";
|
|
675
732
|
}
|
|
676
733
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
677
|
-
return
|
|
734
|
+
return DEV ? "<!--ssr:invalid-tag-->" : "";
|
|
678
735
|
}
|
|
679
736
|
let html2 = `<${tag}`;
|
|
680
737
|
for (const attr of Array.from(element.attributes)) {
|
|
@@ -716,7 +773,7 @@ function hydrate(component, container, options = {}) {
|
|
|
716
773
|
const first = mismatches[0];
|
|
717
774
|
if (options.onMismatch) {
|
|
718
775
|
options.onMismatch(first);
|
|
719
|
-
} else if (
|
|
776
|
+
} else if (DEV) {
|
|
720
777
|
console.warn(
|
|
721
778
|
`[SibuJS hydration] ${first.message}
|
|
722
779
|
at ${first.path}
|
|
@@ -917,11 +974,11 @@ async function* renderToStream(element) {
|
|
|
917
974
|
}
|
|
918
975
|
const tag = element.tagName.toLowerCase();
|
|
919
976
|
if (tag === "script" || tag === "style") {
|
|
920
|
-
if (
|
|
977
|
+
if (DEV) yield `<!--ssr:${tag}-stripped-->`;
|
|
921
978
|
return;
|
|
922
979
|
}
|
|
923
980
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
924
|
-
if (
|
|
981
|
+
if (DEV) yield "<!--ssr:invalid-tag-->";
|
|
925
982
|
return;
|
|
926
983
|
}
|
|
927
984
|
let openTag = `<${tag}`;
|
|
@@ -1064,7 +1121,7 @@ function ssrSuspense(props) {
|
|
|
1064
1121
|
},
|
|
1065
1122
|
(err) => {
|
|
1066
1123
|
if (timer) clearTimeout(timer);
|
|
1067
|
-
if (
|
|
1124
|
+
if (DEV) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
|
|
1068
1125
|
return { id, html: fallbackHtml };
|
|
1069
1126
|
}
|
|
1070
1127
|
);
|
|
@@ -1110,7 +1167,7 @@ function serializeState(state2, nonce, options) {
|
|
|
1110
1167
|
}
|
|
1111
1168
|
function deserializeState(validate) {
|
|
1112
1169
|
if (typeof window === "undefined") return void 0;
|
|
1113
|
-
if (
|
|
1170
|
+
if (DEV && !validate) {
|
|
1114
1171
|
console.warn(
|
|
1115
1172
|
"[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
|
|
1116
1173
|
);
|
|
@@ -1346,7 +1403,14 @@ function reactiveBinding(commit, ownerNode) {
|
|
|
1346
1403
|
subscriber._disposed = false;
|
|
1347
1404
|
subscriber._errorPhase = "binding";
|
|
1348
1405
|
subscriber._errorNode = ownerNode;
|
|
1349
|
-
|
|
1406
|
+
try {
|
|
1407
|
+
run();
|
|
1408
|
+
} catch (err) {
|
|
1409
|
+
subscriber._disposed = true;
|
|
1410
|
+
subscriber._errorNode = void 0;
|
|
1411
|
+
cleanup(subscriber);
|
|
1412
|
+
throw err;
|
|
1413
|
+
}
|
|
1350
1414
|
return subscriber._dispose ?? (subscriber._dispose = () => {
|
|
1351
1415
|
subscriber._disposed = true;
|
|
1352
1416
|
subscriber._errorNode = void 0;
|
|
@@ -1577,17 +1641,16 @@ function forEachSubscriber(signal2, visit) {
|
|
|
1577
1641
|
}
|
|
1578
1642
|
|
|
1579
1643
|
// src/reactivity/track.ts
|
|
1580
|
-
var
|
|
1581
|
-
var _runtimeVersion = true ? "4.0.1" : "dev";
|
|
1644
|
+
var _runtimeVersion = true ? "4.2.0" : "dev";
|
|
1582
1645
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
1583
1646
|
function resolveReactiveApi() {
|
|
1584
1647
|
const g2 = globalThis;
|
|
1585
1648
|
const existing = g2[REGISTRY_KEY];
|
|
1586
1649
|
if (existing) {
|
|
1587
|
-
if (
|
|
1650
|
+
if (DEV && !existing.__dupWarned) {
|
|
1588
1651
|
existing.__dupWarned = true;
|
|
1589
1652
|
devWarn(
|
|
1590
|
-
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity
|
|
1653
|
+
`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.`
|
|
1591
1654
|
);
|
|
1592
1655
|
}
|
|
1593
1656
|
return existing;
|
|
@@ -2090,7 +2153,6 @@ var isBatching = API2.isBatching;
|
|
|
2090
2153
|
|
|
2091
2154
|
// src/core/signals/signal.ts
|
|
2092
2155
|
var _g2 = globalThis;
|
|
2093
|
-
var _isDev5 = isDev();
|
|
2094
2156
|
function signal(initial, options) {
|
|
2095
2157
|
const state2 = {
|
|
2096
2158
|
value: initial,
|
|
@@ -2103,7 +2165,7 @@ function signal(initial, options) {
|
|
|
2103
2165
|
_d: false,
|
|
2104
2166
|
_validate: void 0
|
|
2105
2167
|
};
|
|
2106
|
-
const debugName =
|
|
2168
|
+
const debugName = DEV ? options?.name : void 0;
|
|
2107
2169
|
const equalsFn = options?.equals;
|
|
2108
2170
|
if (debugName) state2.__name = debugName;
|
|
2109
2171
|
function get() {
|
|
@@ -2120,7 +2182,7 @@ function signal(initial, options) {
|
|
|
2120
2182
|
if (equalsFn(prev, newValue)) return;
|
|
2121
2183
|
state2.value = newValue;
|
|
2122
2184
|
state2.__v++;
|
|
2123
|
-
if (
|
|
2185
|
+
if (DEV) {
|
|
2124
2186
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2125
2187
|
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
2126
2188
|
}
|
|
@@ -2128,7 +2190,7 @@ function signal(initial, options) {
|
|
|
2128
2190
|
notifySubscribers2(state2);
|
|
2129
2191
|
}
|
|
2130
2192
|
};
|
|
2131
|
-
} else if (
|
|
2193
|
+
} else if (DEV) {
|
|
2132
2194
|
set = (next) => {
|
|
2133
2195
|
const prev = state2.value;
|
|
2134
2196
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
@@ -2153,7 +2215,7 @@ function signal(initial, options) {
|
|
|
2153
2215
|
}
|
|
2154
2216
|
};
|
|
2155
2217
|
}
|
|
2156
|
-
if (
|
|
2218
|
+
if (DEV) {
|
|
2157
2219
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2158
2220
|
if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
2159
2221
|
}
|
|
@@ -2357,7 +2419,6 @@ function createMiddlewareChain() {
|
|
|
2357
2419
|
}
|
|
2358
2420
|
|
|
2359
2421
|
// src/utils/setSafeAttribute.ts
|
|
2360
|
-
var _isDev6 = isDev();
|
|
2361
2422
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
2362
2423
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2363
2424
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
@@ -2380,7 +2441,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
2380
2441
|
const ns = namespaceFor(el, name);
|
|
2381
2442
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
2382
2443
|
if (isEventHandlerAttr(name)) {
|
|
2383
|
-
if (
|
|
2444
|
+
if (DEV) {
|
|
2384
2445
|
devWarn(
|
|
2385
2446
|
`${options.label ?? "setSafeAttribute"}: refusing to set event-handler attribute "${name}". Its value would be evaluated as JavaScript. Use on:{ ${name.slice(2)}: fn } instead.`
|
|
2386
2447
|
);
|
|
@@ -2395,7 +2456,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
2395
2456
|
return true;
|
|
2396
2457
|
}
|
|
2397
2458
|
if (isHtmlContentAttribute(name)) {
|
|
2398
|
-
if (
|
|
2459
|
+
if (DEV) {
|
|
2399
2460
|
devWarn(
|
|
2400
2461
|
`${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.`
|
|
2401
2462
|
);
|
|
@@ -2424,7 +2485,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
2424
2485
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
2425
2486
|
return true;
|
|
2426
2487
|
}
|
|
2427
|
-
const safe = sanitizeAttributeString(name, str);
|
|
2488
|
+
const safe = sanitizeAttributeString(name, str, { element: el });
|
|
2428
2489
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
2429
2490
|
if (current === safe) return true;
|
|
2430
2491
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -2452,8 +2513,101 @@ function bindAttribute(el, attr, getter) {
|
|
|
2452
2513
|
return reactiveBinding2(commit, el);
|
|
2453
2514
|
}
|
|
2454
2515
|
|
|
2516
|
+
// src/core/rendering/focusPreservation.ts
|
|
2517
|
+
var IDENTITY_ATTRS = ["data-focus-key", "id", "name"];
|
|
2518
|
+
var SELECTABLE_TYPES = /* @__PURE__ */ new Set(["text", "search", "url", "tel", "password", ""]);
|
|
2519
|
+
function selectionOf(el) {
|
|
2520
|
+
const tag = el.tagName;
|
|
2521
|
+
const selectable = tag === "TEXTAREA" || tag === "INPUT" && SELECTABLE_TYPES.has(el.type.toLowerCase());
|
|
2522
|
+
if (!selectable) return { start: null, end: null, direction: null };
|
|
2523
|
+
const field = el;
|
|
2524
|
+
return { start: field.selectionStart, end: field.selectionEnd, direction: field.selectionDirection };
|
|
2525
|
+
}
|
|
2526
|
+
function captureFocusWithin(nodes) {
|
|
2527
|
+
if (nodes.length === 0 || typeof document === "undefined") return null;
|
|
2528
|
+
const active = document.activeElement;
|
|
2529
|
+
if (!active || active === document.body) return null;
|
|
2530
|
+
let inside = false;
|
|
2531
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
2532
|
+
const n = nodes[i2];
|
|
2533
|
+
if (n === active || n.nodeType === 1 && n.contains(active)) {
|
|
2534
|
+
inside = true;
|
|
2535
|
+
break;
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
if (!inside) return null;
|
|
2539
|
+
let attr = null;
|
|
2540
|
+
let value = null;
|
|
2541
|
+
for (let i2 = 0; i2 < IDENTITY_ATTRS.length; i2++) {
|
|
2542
|
+
const candidate = active.getAttribute(IDENTITY_ATTRS[i2]);
|
|
2543
|
+
if (candidate) {
|
|
2544
|
+
attr = IDENTITY_ATTRS[i2];
|
|
2545
|
+
value = candidate;
|
|
2546
|
+
break;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
return { el: active, attr, value, tag: active.tagName, ...selectionOf(active) };
|
|
2550
|
+
}
|
|
2551
|
+
function quote(value) {
|
|
2552
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
2553
|
+
}
|
|
2554
|
+
function findUniqueByIdentity(nodes, selector) {
|
|
2555
|
+
let el = null;
|
|
2556
|
+
let count = 0;
|
|
2557
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
2558
|
+
const n = nodes[i2];
|
|
2559
|
+
if (n.nodeType !== 1) continue;
|
|
2560
|
+
const root = n;
|
|
2561
|
+
if (root.matches(selector)) {
|
|
2562
|
+
count++;
|
|
2563
|
+
el ?? (el = root);
|
|
2564
|
+
}
|
|
2565
|
+
const inner = root.querySelectorAll(selector);
|
|
2566
|
+
for (let j = 0; j < inner.length; j++) {
|
|
2567
|
+
count++;
|
|
2568
|
+
el ?? (el = inner[j]);
|
|
2569
|
+
}
|
|
2570
|
+
if (count > 1) return { el: null, count };
|
|
2571
|
+
}
|
|
2572
|
+
return count === 1 ? { el, count } : { el: null, count };
|
|
2573
|
+
}
|
|
2574
|
+
function refocus(el, snapshot) {
|
|
2575
|
+
el.focus();
|
|
2576
|
+
if (snapshot.start !== null && typeof el.setSelectionRange === "function") {
|
|
2577
|
+
const field = el;
|
|
2578
|
+
const max = field.value.length;
|
|
2579
|
+
const start = Math.min(snapshot.start, max);
|
|
2580
|
+
const end = Math.min(snapshot.end ?? start, max);
|
|
2581
|
+
field.setSelectionRange(start, end, snapshot.direction ?? "none");
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
function restoreFocusWithin(snapshot, nodes, where) {
|
|
2585
|
+
if (!snapshot) return;
|
|
2586
|
+
if (typeof document === "undefined") return;
|
|
2587
|
+
const active = document.activeElement;
|
|
2588
|
+
if (active === snapshot.el) return;
|
|
2589
|
+
if (active && active !== document.body && active !== document.documentElement) return;
|
|
2590
|
+
if (snapshot.el.isConnected) {
|
|
2591
|
+
refocus(snapshot.el, snapshot);
|
|
2592
|
+
return;
|
|
2593
|
+
}
|
|
2594
|
+
let ambiguous = false;
|
|
2595
|
+
if (snapshot.attr && snapshot.value) {
|
|
2596
|
+
const { el: replacement, count } = findUniqueByIdentity(nodes, `[${snapshot.attr}=${quote(snapshot.value)}]`);
|
|
2597
|
+
if (replacement && replacement.tagName === snapshot.tag) {
|
|
2598
|
+
refocus(replacement, snapshot);
|
|
2599
|
+
return;
|
|
2600
|
+
}
|
|
2601
|
+
ambiguous = count > 1;
|
|
2602
|
+
}
|
|
2603
|
+
devWarnLazy(() => {
|
|
2604
|
+
const id = snapshot.attr ? ` (${snapshot.attr}="${snapshot.value}")` : "";
|
|
2605
|
+
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";
|
|
2606
|
+
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.`;
|
|
2607
|
+
});
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2455
2610
|
// src/reactivity/bindChildNode.ts
|
|
2456
|
-
var _isDev7 = isDev();
|
|
2457
2611
|
function bindChildNode(placeholder, getter) {
|
|
2458
2612
|
let lastNodes = [];
|
|
2459
2613
|
function commit() {
|
|
@@ -2464,6 +2618,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2464
2618
|
reportError(err, { phase: "binding", name: "bindChildNode", node: placeholder });
|
|
2465
2619
|
return;
|
|
2466
2620
|
}
|
|
2621
|
+
const focused = captureFocusWithin(lastNodes);
|
|
2467
2622
|
if (result == null || typeof result === "boolean") {
|
|
2468
2623
|
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
2469
2624
|
const node = lastNodes[i2];
|
|
@@ -2471,6 +2626,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2471
2626
|
if (node.parentNode) node.parentNode.removeChild(node);
|
|
2472
2627
|
}
|
|
2473
2628
|
lastNodes.length = 0;
|
|
2629
|
+
restoreFocusWithin(focused, lastNodes, "bindChildNode");
|
|
2474
2630
|
return;
|
|
2475
2631
|
}
|
|
2476
2632
|
const parent = placeholder.parentNode;
|
|
@@ -2487,8 +2643,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2487
2643
|
if (item == null || typeof item === "boolean") continue;
|
|
2488
2644
|
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
2489
2645
|
if (seen.has(node)) {
|
|
2490
|
-
if (
|
|
2491
|
-
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
2646
|
+
if (DEV) devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
2492
2647
|
continue;
|
|
2493
2648
|
}
|
|
2494
2649
|
seen.add(node);
|
|
@@ -2521,13 +2676,13 @@ function bindChildNode(placeholder, getter) {
|
|
|
2521
2676
|
prev = node;
|
|
2522
2677
|
}
|
|
2523
2678
|
lastNodes = newNodes;
|
|
2679
|
+
restoreFocusWithin(focused, newNodes, "bindChildNode");
|
|
2524
2680
|
}
|
|
2525
2681
|
return reactiveBinding2(commit, placeholder);
|
|
2526
2682
|
}
|
|
2527
2683
|
|
|
2528
2684
|
// src/core/rendering/tagFactory.ts
|
|
2529
2685
|
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
2530
|
-
var _isDev8 = isDev();
|
|
2531
2686
|
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
2532
2687
|
function isBlockedTag(tag) {
|
|
2533
2688
|
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
@@ -2545,18 +2700,9 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
|
2545
2700
|
"self",
|
|
2546
2701
|
"frames"
|
|
2547
2702
|
]);
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
const tokens = t.split(/\s+/);
|
|
2552
|
-
let sawClassish = false;
|
|
2553
|
-
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
2554
|
-
const tok = tokens[i2];
|
|
2555
|
-
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return false;
|
|
2556
|
-
if (/[-:/0-9]/.test(tok)) sawClassish = true;
|
|
2557
|
-
}
|
|
2558
|
-
return sawClassish;
|
|
2559
|
-
}
|
|
2703
|
+
var warnedLoneStrings = /* @__PURE__ */ new Set();
|
|
2704
|
+
var MAX_WARNED_LONE_STRINGS = 100;
|
|
2705
|
+
var loneStringCapAnnounced = false;
|
|
2560
2706
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
2561
2707
|
function toKebab(prop) {
|
|
2562
2708
|
let cached = kebabCache.get(prop);
|
|
@@ -2568,13 +2714,13 @@ function toKebab(prop) {
|
|
|
2568
2714
|
function applyStyle(el, style2) {
|
|
2569
2715
|
if (typeof style2 === "function") {
|
|
2570
2716
|
const teardown = reactiveBinding2(() => {
|
|
2571
|
-
el.setAttribute("style", sanitizeStyleAttribute(String(style2())));
|
|
2717
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(style2()), { element: el }));
|
|
2572
2718
|
}, el);
|
|
2573
2719
|
registerDisposer(el, teardown);
|
|
2574
2720
|
return;
|
|
2575
2721
|
}
|
|
2576
2722
|
if (typeof style2 === "string") {
|
|
2577
|
-
el.setAttribute("style", sanitizeStyleAttribute(style2));
|
|
2723
|
+
el.setAttribute("style", sanitizeStyleAttribute(style2, { element: el }));
|
|
2578
2724
|
return;
|
|
2579
2725
|
}
|
|
2580
2726
|
const htmlEl = el;
|
|
@@ -2584,11 +2730,11 @@ function applyStyle(el, style2) {
|
|
|
2584
2730
|
if (typeof val === "function") {
|
|
2585
2731
|
const getter = val;
|
|
2586
2732
|
const teardown = reactiveBinding2(() => {
|
|
2587
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
|
|
2733
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter()), { property: name, element: el }));
|
|
2588
2734
|
}, el);
|
|
2589
2735
|
registerDisposer(el, teardown);
|
|
2590
2736
|
} else {
|
|
2591
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
|
|
2737
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val), { property: name, element: el }));
|
|
2592
2738
|
}
|
|
2593
2739
|
}
|
|
2594
2740
|
}
|
|
@@ -2695,11 +2841,26 @@ var tagFactory = (tag, ns) => {
|
|
|
2695
2841
|
appendChildren(el, second);
|
|
2696
2842
|
return el;
|
|
2697
2843
|
}
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2844
|
+
devWarnLazy(() => {
|
|
2845
|
+
const tokens = first.trim().split(/\s+/);
|
|
2846
|
+
if (tokens.length < 2) return "";
|
|
2847
|
+
let utilityTokens = 0;
|
|
2848
|
+
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
2849
|
+
const tok = tokens[i2];
|
|
2850
|
+
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return "";
|
|
2851
|
+
if (/[-:/0-9]/.test(tok)) utilityTokens++;
|
|
2852
|
+
}
|
|
2853
|
+
if (utilityTokens < 2) return "";
|
|
2854
|
+
const key = `${tag}|${first}`;
|
|
2855
|
+
if (warnedLoneStrings.has(key)) return "";
|
|
2856
|
+
if (warnedLoneStrings.size >= MAX_WARNED_LONE_STRINGS) {
|
|
2857
|
+
if (loneStringCapAnnounced) return "";
|
|
2858
|
+
loneStringCapAnnounced = true;
|
|
2859
|
+
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.`;
|
|
2860
|
+
}
|
|
2861
|
+
warnedLoneStrings.add(key);
|
|
2862
|
+
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.`;
|
|
2863
|
+
});
|
|
2703
2864
|
el.textContent = first;
|
|
2704
2865
|
return el;
|
|
2705
2866
|
}
|
|
@@ -2716,7 +2877,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2716
2877
|
if (pClass != null) applyClass(el, pClass);
|
|
2717
2878
|
const pId = props.id;
|
|
2718
2879
|
if (pId != null) {
|
|
2719
|
-
if (
|
|
2880
|
+
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
2720
2881
|
devWarn(
|
|
2721
2882
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
2722
2883
|
);
|
|
@@ -2731,7 +2892,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2731
2892
|
const handler = pOn[ev];
|
|
2732
2893
|
if (typeof handler === "function") {
|
|
2733
2894
|
el.addEventListener(ev, handler);
|
|
2734
|
-
} else if (
|
|
2895
|
+
} else if (DEV) {
|
|
2735
2896
|
devWarn(
|
|
2736
2897
|
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
2737
2898
|
);
|
package/dist/ssr.js
CHANGED
|
@@ -23,9 +23,9 @@ import {
|
|
|
23
23
|
wasm,
|
|
24
24
|
worker,
|
|
25
25
|
workerFn
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-NEYWS4EX.js";
|
|
27
27
|
import "./chunk-52XFPGSN.js";
|
|
28
|
-
import "./chunk-
|
|
28
|
+
import "./chunk-P3DHXBR6.js";
|
|
29
29
|
import {
|
|
30
30
|
collectStream,
|
|
31
31
|
deserializeState,
|
|
@@ -45,17 +45,17 @@ import {
|
|
|
45
45
|
ssrSuspense,
|
|
46
46
|
suspenseSwapScript,
|
|
47
47
|
trustHTML
|
|
48
|
-
} from "./chunk-
|
|
49
|
-
import "./chunk-
|
|
50
|
-
import "./chunk-
|
|
51
|
-
import "./chunk-
|
|
48
|
+
} from "./chunk-NIOYEGBQ.js";
|
|
49
|
+
import "./chunk-6ZGI3RBE.js";
|
|
50
|
+
import "./chunk-HJEPKZ2O.js";
|
|
51
|
+
import "./chunk-IXKSNWV5.js";
|
|
52
52
|
import "./chunk-7ZHH77QA.js";
|
|
53
|
-
import "./chunk-
|
|
54
|
-
import "./chunk-
|
|
55
|
-
import "./chunk-
|
|
56
|
-
import "./chunk-
|
|
57
|
-
import "./chunk-
|
|
58
|
-
import "./chunk-
|
|
53
|
+
import "./chunk-7VEC3UD2.js";
|
|
54
|
+
import "./chunk-5DXA2J44.js";
|
|
55
|
+
import "./chunk-QKRPLZ2V.js";
|
|
56
|
+
import "./chunk-HECVW343.js";
|
|
57
|
+
import "./chunk-7ALC7KGE.js";
|
|
58
|
+
import "./chunk-2WLZ6757.js";
|
|
59
59
|
export {
|
|
60
60
|
Head,
|
|
61
61
|
clearWasmCache,
|