sibujs 4.1.0 → 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 +24 -0
- package/dist/browser.cjs +13 -21
- package/dist/browser.js +6 -6
- package/dist/build.cjs +278 -104
- package/dist/build.js +15 -15
- package/dist/cdn.dev.global.js +398 -0
- package/dist/cdn.global.js +10 -10
- package/dist/{chunk-DCDS2PQ6.js → chunk-2LOYNGBY.js} +2 -2
- package/dist/{chunk-VPP2FONR.js → chunk-2WLZ6757.js} +17 -10
- package/dist/{chunk-IM7N5WR4.js → chunk-3VTSPNC5.js} +2 -2
- package/dist/{chunk-TIRZCERI.js → chunk-5DXA2J44.js} +1 -1
- package/dist/{chunk-I3VI34DP.js → chunk-6ZGI3RBE.js} +149 -33
- package/dist/{chunk-D3SZ4LVS.js → chunk-7ALC7KGE.js} +5 -6
- package/dist/{chunk-PFTDGEPZ.js → chunk-7VEC3UD2.js} +3 -3
- package/dist/{chunk-KSOEJGFO.js → chunk-BMYYZWHX.js} +3 -3
- package/dist/{chunk-LOFZHP6V.js → chunk-BNKV4REK.js} +7 -8
- package/dist/{chunk-5GJ5RTHA.js → chunk-FOWBJZDL.js} +7 -8
- package/dist/{chunk-FB7KQXZI.js → chunk-GDUNQCCW.js} +4 -4
- package/dist/{chunk-UFSQEO7P.js → chunk-HECVW343.js} +7 -8
- package/dist/{chunk-SHDVWATN.js → chunk-HJEPKZ2O.js} +7 -8
- package/dist/{chunk-ANGSYNPX.js → chunk-HZEBO22J.js} +57 -37
- package/dist/{chunk-5INI7D2L.js → chunk-IXKSNWV5.js} +74 -11
- package/dist/{chunk-DAKLOMKS.js → chunk-KE4KWRDY.js} +3 -3
- package/dist/{chunk-AW6HPJ3L.js → chunk-KKLW7YWL.js} +1 -1
- package/dist/{chunk-BMSN6NWQ.js → chunk-NEYWS4EX.js} +6 -6
- package/dist/{chunk-HYCCIYNS.js → chunk-NIOYEGBQ.js} +13 -14
- package/dist/{chunk-4U7KD3RY.js → chunk-OUWAIXIK.js} +3 -3
- package/dist/{chunk-MRAMKDHQ.js → chunk-P3DHXBR6.js} +1 -1
- package/dist/{chunk-FMHIQNMP.js → chunk-QCFLDD7C.js} +5 -5
- package/dist/{chunk-DHDZ7IVN.js → chunk-QKRPLZ2V.js} +7 -8
- package/dist/{chunk-4RH6D7GR.js → chunk-QL4UREZO.js} +6 -6
- package/dist/{chunk-XIHMS2Y6.js → chunk-SF3TB4K6.js} +8 -8
- package/dist/{chunk-XSZRJW76.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 +15 -24
- package/dist/data.js +9 -9
- package/dist/devtools.cjs +18 -22
- 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 +222 -67
- package/dist/ecosystem.js +11 -11
- package/dist/extras.cjs +243 -86
- package/dist/extras.d.cts +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/extras.js +25 -25
- package/dist/index.cjs +272 -98
- package/dist/index.d.cts +154 -33
- package/dist/index.d.ts +154 -33
- package/dist/index.js +15 -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 +13 -22
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +16 -24
- package/dist/patterns.d.cts +8 -0
- package/dist/patterns.d.ts +8 -0
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +16 -27
- package/dist/performance.js +9 -9
- package/dist/plugins.cjs +260 -86
- 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 +233 -79
- package/dist/ssr.js +12 -12
- package/dist/testing.cjs +11 -19
- package/dist/testing.js +5 -5
- package/dist/ui.cjs +98 -43
- package/dist/ui.d.cts +7 -1
- package/dist/ui.d.ts +7 -1
- package/dist/ui.js +10 -10
- package/dist/widgets.cjs +13 -21
- package/dist/widgets.d.cts +8 -0
- package/dist/widgets.d.ts +8 -0
- package/dist/widgets.js +9 -9
- package/package.json +5 -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;
|
|
397
445
|
}
|
|
398
|
-
function
|
|
446
|
+
function sanitizeCSSValue(value, context) {
|
|
447
|
+
const reason = blockedCssReason(value);
|
|
448
|
+
if (reason === -1) return value;
|
|
449
|
+
warnDroppedDeclaration(value, reason, context);
|
|
450
|
+
return "";
|
|
451
|
+
}
|
|
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
|
);
|
|
@@ -1584,17 +1641,16 @@ function forEachSubscriber(signal2, visit) {
|
|
|
1584
1641
|
}
|
|
1585
1642
|
|
|
1586
1643
|
// src/reactivity/track.ts
|
|
1587
|
-
var
|
|
1588
|
-
var _runtimeVersion = true ? "4.1.0" : "dev";
|
|
1644
|
+
var _runtimeVersion = true ? "4.2.0" : "dev";
|
|
1589
1645
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
1590
1646
|
function resolveReactiveApi() {
|
|
1591
1647
|
const g2 = globalThis;
|
|
1592
1648
|
const existing = g2[REGISTRY_KEY];
|
|
1593
1649
|
if (existing) {
|
|
1594
|
-
if (
|
|
1650
|
+
if (DEV && !existing.__dupWarned) {
|
|
1595
1651
|
existing.__dupWarned = true;
|
|
1596
1652
|
devWarn(
|
|
1597
|
-
`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.`
|
|
1598
1654
|
);
|
|
1599
1655
|
}
|
|
1600
1656
|
return existing;
|
|
@@ -2097,7 +2153,6 @@ var isBatching = API2.isBatching;
|
|
|
2097
2153
|
|
|
2098
2154
|
// src/core/signals/signal.ts
|
|
2099
2155
|
var _g2 = globalThis;
|
|
2100
|
-
var _isDev5 = isDev();
|
|
2101
2156
|
function signal(initial, options) {
|
|
2102
2157
|
const state2 = {
|
|
2103
2158
|
value: initial,
|
|
@@ -2110,7 +2165,7 @@ function signal(initial, options) {
|
|
|
2110
2165
|
_d: false,
|
|
2111
2166
|
_validate: void 0
|
|
2112
2167
|
};
|
|
2113
|
-
const debugName =
|
|
2168
|
+
const debugName = DEV ? options?.name : void 0;
|
|
2114
2169
|
const equalsFn = options?.equals;
|
|
2115
2170
|
if (debugName) state2.__name = debugName;
|
|
2116
2171
|
function get() {
|
|
@@ -2127,7 +2182,7 @@ function signal(initial, options) {
|
|
|
2127
2182
|
if (equalsFn(prev, newValue)) return;
|
|
2128
2183
|
state2.value = newValue;
|
|
2129
2184
|
state2.__v++;
|
|
2130
|
-
if (
|
|
2185
|
+
if (DEV) {
|
|
2131
2186
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2132
2187
|
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
2133
2188
|
}
|
|
@@ -2135,7 +2190,7 @@ function signal(initial, options) {
|
|
|
2135
2190
|
notifySubscribers2(state2);
|
|
2136
2191
|
}
|
|
2137
2192
|
};
|
|
2138
|
-
} else if (
|
|
2193
|
+
} else if (DEV) {
|
|
2139
2194
|
set = (next) => {
|
|
2140
2195
|
const prev = state2.value;
|
|
2141
2196
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
@@ -2160,7 +2215,7 @@ function signal(initial, options) {
|
|
|
2160
2215
|
}
|
|
2161
2216
|
};
|
|
2162
2217
|
}
|
|
2163
|
-
if (
|
|
2218
|
+
if (DEV) {
|
|
2164
2219
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2165
2220
|
if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
2166
2221
|
}
|
|
@@ -2364,7 +2419,6 @@ function createMiddlewareChain() {
|
|
|
2364
2419
|
}
|
|
2365
2420
|
|
|
2366
2421
|
// src/utils/setSafeAttribute.ts
|
|
2367
|
-
var _isDev6 = isDev();
|
|
2368
2422
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
2369
2423
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2370
2424
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
@@ -2387,7 +2441,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
2387
2441
|
const ns = namespaceFor(el, name);
|
|
2388
2442
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
2389
2443
|
if (isEventHandlerAttr(name)) {
|
|
2390
|
-
if (
|
|
2444
|
+
if (DEV) {
|
|
2391
2445
|
devWarn(
|
|
2392
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.`
|
|
2393
2447
|
);
|
|
@@ -2402,7 +2456,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
2402
2456
|
return true;
|
|
2403
2457
|
}
|
|
2404
2458
|
if (isHtmlContentAttribute(name)) {
|
|
2405
|
-
if (
|
|
2459
|
+
if (DEV) {
|
|
2406
2460
|
devWarn(
|
|
2407
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.`
|
|
2408
2462
|
);
|
|
@@ -2431,7 +2485,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
2431
2485
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
2432
2486
|
return true;
|
|
2433
2487
|
}
|
|
2434
|
-
const safe = sanitizeAttributeString(name, str);
|
|
2488
|
+
const safe = sanitizeAttributeString(name, str, { element: el });
|
|
2435
2489
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
2436
2490
|
if (current === safe) return true;
|
|
2437
2491
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -2459,8 +2513,101 @@ function bindAttribute(el, attr, getter) {
|
|
|
2459
2513
|
return reactiveBinding2(commit, el);
|
|
2460
2514
|
}
|
|
2461
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
|
+
|
|
2462
2610
|
// src/reactivity/bindChildNode.ts
|
|
2463
|
-
var _isDev7 = isDev();
|
|
2464
2611
|
function bindChildNode(placeholder, getter) {
|
|
2465
2612
|
let lastNodes = [];
|
|
2466
2613
|
function commit() {
|
|
@@ -2471,6 +2618,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2471
2618
|
reportError(err, { phase: "binding", name: "bindChildNode", node: placeholder });
|
|
2472
2619
|
return;
|
|
2473
2620
|
}
|
|
2621
|
+
const focused = captureFocusWithin(lastNodes);
|
|
2474
2622
|
if (result == null || typeof result === "boolean") {
|
|
2475
2623
|
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
2476
2624
|
const node = lastNodes[i2];
|
|
@@ -2478,6 +2626,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2478
2626
|
if (node.parentNode) node.parentNode.removeChild(node);
|
|
2479
2627
|
}
|
|
2480
2628
|
lastNodes.length = 0;
|
|
2629
|
+
restoreFocusWithin(focused, lastNodes, "bindChildNode");
|
|
2481
2630
|
return;
|
|
2482
2631
|
}
|
|
2483
2632
|
const parent = placeholder.parentNode;
|
|
@@ -2494,8 +2643,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2494
2643
|
if (item == null || typeof item === "boolean") continue;
|
|
2495
2644
|
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
2496
2645
|
if (seen.has(node)) {
|
|
2497
|
-
if (
|
|
2498
|
-
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.");
|
|
2499
2647
|
continue;
|
|
2500
2648
|
}
|
|
2501
2649
|
seen.add(node);
|
|
@@ -2528,13 +2676,13 @@ function bindChildNode(placeholder, getter) {
|
|
|
2528
2676
|
prev = node;
|
|
2529
2677
|
}
|
|
2530
2678
|
lastNodes = newNodes;
|
|
2679
|
+
restoreFocusWithin(focused, newNodes, "bindChildNode");
|
|
2531
2680
|
}
|
|
2532
2681
|
return reactiveBinding2(commit, placeholder);
|
|
2533
2682
|
}
|
|
2534
2683
|
|
|
2535
2684
|
// src/core/rendering/tagFactory.ts
|
|
2536
2685
|
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
2537
|
-
var _isDev8 = isDev();
|
|
2538
2686
|
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
2539
2687
|
function isBlockedTag(tag) {
|
|
2540
2688
|
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
@@ -2552,18 +2700,9 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
|
2552
2700
|
"self",
|
|
2553
2701
|
"frames"
|
|
2554
2702
|
]);
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
const tokens = t.split(/\s+/);
|
|
2559
|
-
let sawClassish = false;
|
|
2560
|
-
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
2561
|
-
const tok = tokens[i2];
|
|
2562
|
-
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return false;
|
|
2563
|
-
if (/[-:/0-9]/.test(tok)) sawClassish = true;
|
|
2564
|
-
}
|
|
2565
|
-
return sawClassish;
|
|
2566
|
-
}
|
|
2703
|
+
var warnedLoneStrings = /* @__PURE__ */ new Set();
|
|
2704
|
+
var MAX_WARNED_LONE_STRINGS = 100;
|
|
2705
|
+
var loneStringCapAnnounced = false;
|
|
2567
2706
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
2568
2707
|
function toKebab(prop) {
|
|
2569
2708
|
let cached = kebabCache.get(prop);
|
|
@@ -2575,13 +2714,13 @@ function toKebab(prop) {
|
|
|
2575
2714
|
function applyStyle(el, style2) {
|
|
2576
2715
|
if (typeof style2 === "function") {
|
|
2577
2716
|
const teardown = reactiveBinding2(() => {
|
|
2578
|
-
el.setAttribute("style", sanitizeStyleAttribute(String(style2())));
|
|
2717
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(style2()), { element: el }));
|
|
2579
2718
|
}, el);
|
|
2580
2719
|
registerDisposer(el, teardown);
|
|
2581
2720
|
return;
|
|
2582
2721
|
}
|
|
2583
2722
|
if (typeof style2 === "string") {
|
|
2584
|
-
el.setAttribute("style", sanitizeStyleAttribute(style2));
|
|
2723
|
+
el.setAttribute("style", sanitizeStyleAttribute(style2, { element: el }));
|
|
2585
2724
|
return;
|
|
2586
2725
|
}
|
|
2587
2726
|
const htmlEl = el;
|
|
@@ -2591,11 +2730,11 @@ function applyStyle(el, style2) {
|
|
|
2591
2730
|
if (typeof val === "function") {
|
|
2592
2731
|
const getter = val;
|
|
2593
2732
|
const teardown = reactiveBinding2(() => {
|
|
2594
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
|
|
2733
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter()), { property: name, element: el }));
|
|
2595
2734
|
}, el);
|
|
2596
2735
|
registerDisposer(el, teardown);
|
|
2597
2736
|
} else {
|
|
2598
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
|
|
2737
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val), { property: name, element: el }));
|
|
2599
2738
|
}
|
|
2600
2739
|
}
|
|
2601
2740
|
}
|
|
@@ -2702,11 +2841,26 @@ var tagFactory = (tag, ns) => {
|
|
|
2702
2841
|
appendChildren(el, second);
|
|
2703
2842
|
return el;
|
|
2704
2843
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
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
|
+
});
|
|
2710
2864
|
el.textContent = first;
|
|
2711
2865
|
return el;
|
|
2712
2866
|
}
|
|
@@ -2723,7 +2877,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2723
2877
|
if (pClass != null) applyClass(el, pClass);
|
|
2724
2878
|
const pId = props.id;
|
|
2725
2879
|
if (pId != null) {
|
|
2726
|
-
if (
|
|
2880
|
+
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
2727
2881
|
devWarn(
|
|
2728
2882
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
2729
2883
|
);
|
|
@@ -2738,7 +2892,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2738
2892
|
const handler = pOn[ev];
|
|
2739
2893
|
if (typeof handler === "function") {
|
|
2740
2894
|
el.addEventListener(ev, handler);
|
|
2741
|
-
} else if (
|
|
2895
|
+
} else if (DEV) {
|
|
2742
2896
|
devWarn(
|
|
2743
2897
|
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
2744
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,
|