sibujs 4.11.0 → 4.12.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.
Files changed (79) hide show
  1. package/README.md +2 -2
  2. package/dist/browser.cjs +1 -1
  3. package/dist/browser.js +4 -4
  4. package/dist/build.cjs +19 -1
  5. package/dist/build.js +13 -12
  6. package/dist/cdn.dev.global.js +12 -12
  7. package/dist/cdn.full.dev.global.js +13 -13
  8. package/dist/cdn.full.global.js +12 -12
  9. package/dist/cdn.global.js +12 -12
  10. package/dist/{chunk-FC6KCJSA.js → chunk-2F4PSJ5Z.js} +162 -67
  11. package/dist/{chunk-R244COCR.js → chunk-653KGQS2.js} +3 -3
  12. package/dist/chunk-AM6DZLBM.js +181 -0
  13. package/dist/{chunk-ADWDDJ5M.js → chunk-B2Y5BJSP.js} +1 -1
  14. package/dist/{chunk-KREPZR2U.js → chunk-CI4W6XAU.js} +4 -4
  15. package/dist/{chunk-NBBFF5VA.js → chunk-DFZL3AX7.js} +6 -6
  16. package/dist/{chunk-OJV2RW4D.js → chunk-EMB5PG7V.js} +1 -1
  17. package/dist/{chunk-3ACAAQIN.js → chunk-F2UWOZ6J.js} +4 -0
  18. package/dist/{chunk-REOAVT2M.js → chunk-HXT2RNH5.js} +1 -1
  19. package/dist/{chunk-F6B5CKF7.js → chunk-IHA62NGJ.js} +1 -1
  20. package/dist/{chunk-VZDMHDVA.js → chunk-LEUEKK4G.js} +2 -2
  21. package/dist/{chunk-WQ7M57JJ.js → chunk-LXBMVGVB.js} +3 -3
  22. package/dist/{chunk-RRKGQKPU.js → chunk-LYTUTXQP.js} +4 -4
  23. package/dist/{chunk-5IODQRR3.js → chunk-NAVLCP4S.js} +4 -4
  24. package/dist/{chunk-YXJHLMRH.js → chunk-NB7TFSJE.js} +5 -5
  25. package/dist/{chunk-5G53CC6L.js → chunk-QLG5IK7F.js} +4 -4
  26. package/dist/{chunk-KFJUMC3Q.js → chunk-RK7EPQPG.js} +1 -1
  27. package/dist/{chunk-LQ2C44YH.js → chunk-T5O2CUHV.js} +1 -1
  28. package/dist/{chunk-CHQPJY47.js → chunk-WFRQ6D7H.js} +1 -1
  29. package/dist/{chunk-3Z7AEJMQ.js → chunk-WH4U2VUE.js} +5 -3
  30. package/dist/{chunk-HMOPAC2Z.js → chunk-XX4BRMWF.js} +15 -3
  31. package/dist/{chunk-7V7VFT7E.js → chunk-ZJCHY2IB.js} +1 -1
  32. package/dist/{chunk-MCPL5WKQ.js → chunk-ZPY2UAKM.js} +3 -3
  33. package/dist/{chunk-DEUONJYR.js → chunk-ZTYCCBU3.js} +19 -11
  34. package/dist/data.cjs +1 -1
  35. package/dist/data.js +5 -5
  36. package/dist/devtools.cjs +1 -1
  37. package/dist/devtools.js +4 -4
  38. package/dist/ecosystem.cjs +9 -1
  39. package/dist/ecosystem.d.cts +1 -1
  40. package/dist/ecosystem.d.ts +1 -1
  41. package/dist/ecosystem.js +8 -8
  42. package/dist/extras.cjs +368 -154
  43. package/dist/extras.d.cts +2 -2
  44. package/dist/extras.d.ts +2 -2
  45. package/dist/extras.js +23 -22
  46. package/dist/index.cjs +19 -1
  47. package/dist/index.d.cts +91 -90
  48. package/dist/index.d.ts +91 -90
  49. package/dist/index.js +13 -12
  50. package/dist/motion.cjs +1 -1
  51. package/dist/motion.js +3 -3
  52. package/dist/patterns.cjs +1 -1
  53. package/dist/patterns.js +5 -5
  54. package/dist/performance.cjs +1 -1
  55. package/dist/performance.d.cts +2 -2
  56. package/dist/performance.d.ts +2 -2
  57. package/dist/performance.js +7 -6
  58. package/dist/plugins.cjs +344 -109
  59. package/dist/plugins.d.cts +1 -1
  60. package/dist/plugins.d.ts +1 -1
  61. package/dist/plugins.js +15 -12
  62. package/dist/{ssr-C8hgIAw7.d.cts → ssr-Db0Sgdu3.d.cts} +7 -4
  63. package/dist/{ssr-C8hgIAw7.d.ts → ssr-Db0Sgdu3.d.ts} +7 -4
  64. package/dist/{ssr-5OWAH3U2.js → ssr-VBM6J5SJ.js} +4 -2
  65. package/dist/ssr.cjs +346 -128
  66. package/dist/ssr.d.cts +1 -1
  67. package/dist/ssr.d.ts +1 -1
  68. package/dist/ssr.js +10 -9
  69. package/dist/{tagFactory-BL2fymez.d.ts → tagFactory-Bnd_Nph9.d.ts} +1 -1
  70. package/dist/{tagFactory-8qL9LCIx.d.cts → tagFactory-DkytnJws.d.cts} +1 -1
  71. package/dist/testing.cjs +1 -1
  72. package/dist/testing.js +2 -2
  73. package/dist/ui.cjs +251 -24
  74. package/dist/ui.d.cts +111 -1
  75. package/dist/ui.d.ts +111 -1
  76. package/dist/ui.js +130 -8
  77. package/dist/widgets.cjs +1 -1
  78. package/dist/widgets.js +6 -6
  79. package/package.json +1 -1
package/dist/plugins.cjs CHANGED
@@ -699,6 +699,9 @@ function contextualAttributeRefusal(el, name, value, origin) {
699
699
  if (SVG_ANIMATION_ELEMENTS.has(local) && el.namespaceURI === SVG_NS) return animationRefusal(name, value);
700
700
  return ContextualRefusal.None;
701
701
  }
702
+ function isRefusedAnimationAttribute(el, name, value) {
703
+ return SVG_ANIMATION_ELEMENTS.has(el.localName) && el.namespaceURI === SVG_NS && animationRefusal(name, value) !== ContextualRefusal.None;
704
+ }
702
705
  function settleAttributeProvenance(el, name, origin) {
703
706
  if (el.localName !== "link" || canonicalAttrName(name) !== "href") return;
704
707
  if (origin !== "static" && el.hasAttribute("href")) runtimeHrefLinks.add(el);
@@ -966,6 +969,140 @@ var init_ssr_context = __esm({
966
969
  }
967
970
  });
968
971
 
972
+ // src/utils/globalSingleton.ts
973
+ function globalSingleton(key, create) {
974
+ const g2 = globalThis;
975
+ return g2[key] ?? (g2[key] = create());
976
+ }
977
+ var init_globalSingleton = __esm({
978
+ "src/utils/globalSingleton.ts"() {
979
+ "use strict";
980
+ }
981
+ });
982
+
983
+ // src/utils/embedPolicy.ts
984
+ function currentEmbedAllowlist() {
985
+ const scoped = getRequestStore()?.caches?.get(REQUEST_CACHE)?.get("allowed");
986
+ return scoped ?? state2.allowed;
987
+ }
988
+ function resolveEmbedSrc(value, allowed = currentEmbedAllowlist()) {
989
+ if (typeof value !== "string" || sanitizeUrl(value) === "") return null;
990
+ let url;
991
+ try {
992
+ url = new URL(value);
993
+ } catch {
994
+ return null;
995
+ }
996
+ if (url.protocol !== "https:" || url.username || url.password) return null;
997
+ if (typeof location !== "undefined" && url.origin === location.origin) return null;
998
+ for (const entry of allowed) {
999
+ if (url.origin !== entry.origin) continue;
1000
+ const path2 = entry.path;
1001
+ if (path2 === "" || url.pathname === path2 || url.pathname.startsWith(path2.endsWith("/") ? path2 : `${path2}/`)) {
1002
+ return url.href;
1003
+ }
1004
+ }
1005
+ return null;
1006
+ }
1007
+ function narrowEmbedSandbox(value) {
1008
+ const out = [];
1009
+ for (const token of value.toLowerCase().split(/[\t\n\f\r ]+/)) {
1010
+ if (token && DEFAULT_EMBED_SANDBOX.includes(token) && !out.includes(token)) out.push(token);
1011
+ }
1012
+ return out.join(" ");
1013
+ }
1014
+ function narrowEmbedAllow(value) {
1015
+ const granted = [];
1016
+ const denied = [];
1017
+ for (const directive of value.split(";")) {
1018
+ const tokens = directive.trim().split(/[\t\n\f\r ]+/);
1019
+ const feature = tokens[0];
1020
+ if (!feature) continue;
1021
+ const list = tokens.slice(1).map((token) => token.toLowerCase());
1022
+ const grantsSrc = (list.length === 0 || list.includes("'src'") || list.includes("*")) && !list.includes("'none'");
1023
+ if (!grantsSrc) denied.push(feature);
1024
+ else if (EMBED_FEATURES.has(feature) && !granted.includes(feature)) granted.push(feature);
1025
+ }
1026
+ return granted.filter((feature) => !denied.includes(feature)).join("; ");
1027
+ }
1028
+ function getEmbedRecord(frame) {
1029
+ return state2.frames.get(frame);
1030
+ }
1031
+ function intersect(current, permitted, separator) {
1032
+ const allowed = permitted.split(separator);
1033
+ return current.split(separator).filter((token) => token && allowed.includes(token)).join(separator);
1034
+ }
1035
+ function embedSerializedAttribute(record, seen, name, value) {
1036
+ switch (name) {
1037
+ case "src":
1038
+ return resolveEmbedSrc(value, record.allowed);
1039
+ case "title":
1040
+ if (!value.trim()) return null;
1041
+ seen.title = true;
1042
+ return value;
1043
+ case "sandbox":
1044
+ seen.sandbox = true;
1045
+ return intersect(narrowEmbedSandbox(value), record.sandbox, " ");
1046
+ case "allow": {
1047
+ const allow = intersect(narrowEmbedAllow(value), record.allow, "; ");
1048
+ if (allow.split("; ").includes("fullscreen")) seen.fullscreen = true;
1049
+ return allow || null;
1050
+ }
1051
+ case "referrerpolicy":
1052
+ seen.referrer = true;
1053
+ return value.trim().toLowerCase() === "no-referrer" ? "no-referrer" : record.referrer;
1054
+ case "loading":
1055
+ return value === "eager" ? "eager" : "lazy";
1056
+ case "id":
1057
+ case "class":
1058
+ case "style":
1059
+ case "width":
1060
+ case "height":
1061
+ return value;
1062
+ default:
1063
+ return name.startsWith("data-") || name.startsWith("aria-") ? value : null;
1064
+ }
1065
+ }
1066
+ function embedSerializationTail(record, seen) {
1067
+ if (!seen.title) return null;
1068
+ let tail = "";
1069
+ if (!seen.sandbox) tail += ` sandbox="${record.sandbox}"`;
1070
+ if (!seen.referrer) tail += ` referrerpolicy="${record.referrer}"`;
1071
+ if (seen.fullscreen) tail += ' allowfullscreen=""';
1072
+ return tail;
1073
+ }
1074
+ var state2, REQUEST_CACHE, DEFAULT_EMBED_SANDBOX, EMBED_FEATURES;
1075
+ var init_embedPolicy = __esm({
1076
+ "src/utils/embedPolicy.ts"() {
1077
+ "use strict";
1078
+ init_ssr_context();
1079
+ init_globalSingleton();
1080
+ init_sanitize();
1081
+ state2 = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.embed.v2"), () => ({
1082
+ allowed: [],
1083
+ frames: /* @__PURE__ */ new WeakMap()
1084
+ }));
1085
+ REQUEST_CACHE = "embed";
1086
+ DEFAULT_EMBED_SANDBOX = [
1087
+ "allow-scripts",
1088
+ "allow-same-origin",
1089
+ "allow-presentation",
1090
+ "allow-popups",
1091
+ "allow-popups-to-escape-sandbox"
1092
+ ];
1093
+ EMBED_FEATURES = /* @__PURE__ */ new Set([
1094
+ "accelerometer",
1095
+ "autoplay",
1096
+ "clipboard-write",
1097
+ "encrypted-media",
1098
+ "fullscreen",
1099
+ "gyroscope",
1100
+ "picture-in-picture",
1101
+ "web-share"
1102
+ ]);
1103
+ }
1104
+ });
1105
+
969
1106
  // src/utils/guards.ts
970
1107
  function isUnsafeKey(key) {
971
1108
  return UNSAFE_KEYS.has(key);
@@ -1133,69 +1270,129 @@ function childNodesOf(node) {
1133
1270
  function getAttributeOf(el, name) {
1134
1271
  return nativeAccessors().getAttribute.call(el, name);
1135
1272
  }
1136
- function serializeOpenTag(element, tag) {
1273
+ function isBreakout(lowerName, element) {
1274
+ if (BREAKOUT_TAGS.has(lowerName)) return true;
1275
+ return lowerName === "font" && (element.hasAttribute("color") || element.hasAttribute("face") || element.hasAttribute("size"));
1276
+ }
1277
+ function fitsParseContext(ns, lowerName, element, context) {
1278
+ if (ns === SVG_NS4) {
1279
+ if (context === 1 /* Svg */) return !isBreakout(lowerName, element);
1280
+ return lowerName === "svg" && (context === 0 /* Html */ || context === 3 /* Annotation */);
1281
+ }
1282
+ if (ns === MATHML_NS) {
1283
+ if (context === 2 /* Math */ || context === 3 /* Annotation */) return !isBreakout(lowerName, element);
1284
+ return lowerName === "math" && context === 0 /* Html */;
1285
+ }
1286
+ return context === 0 /* Html */;
1287
+ }
1288
+ function childParseContext(ns, lowerName, element) {
1289
+ if (ns === SVG_NS4) {
1290
+ return lowerName === "foreignobject" || lowerName === "desc" || lowerName === "title" ? 0 /* Html */ : 1 /* Svg */;
1291
+ }
1292
+ if (ns === MATHML_NS) {
1293
+ if (lowerName === "mi" || lowerName === "mo" || lowerName === "mn" || lowerName === "ms" || lowerName === "mtext") {
1294
+ return 0 /* Html */;
1295
+ }
1296
+ if (lowerName === "annotation-xml") {
1297
+ const encoding = (element.getAttribute("encoding") ?? "").toLowerCase();
1298
+ return encoding === "text/html" || encoding === "application/xhtml+xml" ? 0 /* Html */ : 3 /* Annotation */;
1299
+ }
1300
+ return 2 /* Math */;
1301
+ }
1302
+ return 0 /* Html */;
1303
+ }
1304
+ function foreignAttrName(attr) {
1305
+ const ns = attr.namespaceURI;
1306
+ if (ns === XLINK_NS2) return `xlink:${attr.localName}`;
1307
+ if (ns === XML_NS2) return `xml:${attr.localName}`;
1308
+ if (ns === XMLNS_NS) return attr.localName === "xmlns" ? "xmlns" : `xmlns:${attr.localName}`;
1309
+ return attr.name;
1310
+ }
1311
+ function serializeOpenTag(element, tag, foreign) {
1137
1312
  let html2 = `<${tag}`;
1138
- const meta2 = tag === "meta" ? /* @__PURE__ */ new Map() : null;
1313
+ const meta2 = tag === "meta" && !foreign ? /* @__PURE__ */ new Map() : null;
1314
+ const embed2 = tag === "iframe" && !foreign ? getEmbedRecord(element) : void 0;
1315
+ const embedSeen = embed2 ? { sandbox: false, referrer: false, title: false, fullscreen: false } : null;
1139
1316
  const attrs = attributesOf(element);
1140
1317
  for (let i2 = 0; i2 < attrs.length; i2++) {
1141
1318
  const attr = attrs[i2];
1142
- const rawName = attr.name;
1319
+ const rawName = foreign ? foreignAttrName(attr) : attr.name;
1143
1320
  if (!isSafeAttrName(rawName)) continue;
1144
1321
  if (isEventHandlerAttr(rawName)) continue;
1145
1322
  if (isForbiddenSsrAttr(rawName)) continue;
1146
- const value = resolveAttributeValue(rawName.toLowerCase(), attr.value);
1323
+ const lowerName = rawName.toLowerCase();
1324
+ let value = resolveAttributeValue(lowerName, attr.value);
1147
1325
  if (value === null) continue;
1326
+ if (foreign && isRefusedAnimationAttribute(element, rawName, value)) continue;
1327
+ if (embed2 && embedSeen) {
1328
+ value = embedSerializedAttribute(embed2, embedSeen, lowerName, value);
1329
+ if (value === null) continue;
1330
+ }
1148
1331
  meta2?.set(rawName, value);
1149
1332
  html2 += ` ${rawName}="${escapeAttr(value)}"`;
1150
1333
  }
1151
1334
  if (meta2 && isForbiddenMetaSnapshot(meta2)) return null;
1335
+ if (embed2 && embedSeen) {
1336
+ const tail = embedSerializationTail(embed2, embedSeen);
1337
+ if (tail === null) return null;
1338
+ html2 += tail;
1339
+ }
1152
1340
  if (!getAttributeOf(element, "data-sibu-hydrate")) {
1153
1341
  html2 += ` data-sibu-ssr="true"`;
1154
1342
  }
1155
1343
  return html2;
1156
1344
  }
1345
+ function serializeNode(node, context) {
1346
+ if (node.nodeType === 3) return escapeHtml(node.textContent || "");
1347
+ if (node.nodeType === 8) return `<!--${safeCommentText(node.textContent || "")}-->`;
1348
+ let foreign = false;
1349
+ if (!(node instanceof HTMLElement)) {
1350
+ const ns2 = node.nodeType === 1 ? node.namespaceURI : null;
1351
+ if (ns2 !== SVG_NS4 && ns2 !== MATHML_NS) return escapeHtml(node.textContent || "");
1352
+ foreign = true;
1353
+ }
1354
+ const element = node;
1355
+ const tag = foreign ? element.localName : tagNameOf(element).toLowerCase();
1356
+ if (isCodeTextElement(tag)) return DEV ? `<!--ssr:${tag}-stripped-->` : "";
1357
+ if (!/^[a-z][a-z0-9-]*$/i.test(tag)) return DEV ? "<!--ssr:invalid-tag-->" : "";
1358
+ const ns = foreign ? element.namespaceURI : null;
1359
+ const lowerName = tag.toLowerCase();
1360
+ if (!fitsParseContext(ns, lowerName, element, context)) return DEV ? `<!--ssr:${tag}-misplaced-->` : "";
1361
+ const openTag = serializeOpenTag(element, tag, foreign);
1362
+ if (openTag === null) return DEV ? `<!--ssr:${tag}-stripped-->` : "";
1363
+ const children = childNodesOf(element);
1364
+ if (foreign ? children.length === 0 : VOID_ELEMENTS.has(tag)) return `${openTag} />`;
1365
+ return {
1366
+ open: `${openTag}>`,
1367
+ close: `</${tag}>`,
1368
+ children: Array.from(children),
1369
+ context: childParseContext(ns, lowerName, element)
1370
+ };
1371
+ }
1157
1372
  function renderToString(element) {
1373
+ return renderNodeToString(element, 0 /* Html */);
1374
+ }
1375
+ function renderNodeToString(element, context) {
1158
1376
  if (element instanceof DocumentFragment) {
1159
1377
  return Array.from(element.childNodes).map((child) => {
1160
1378
  try {
1161
- return renderToString(child);
1379
+ return renderNodeToString(child, context);
1162
1380
  } catch (err) {
1163
1381
  return ssrErrorComment(err);
1164
1382
  }
1165
1383
  }).join("");
1166
1384
  }
1167
- if (element.nodeType === 3) {
1168
- return escapeHtml(element.textContent || "");
1169
- }
1170
- if (element.nodeType === 8) {
1171
- return `<!--${safeCommentText(element.textContent || "")}-->`;
1172
- }
1173
- if (!(element instanceof HTMLElement)) {
1174
- return escapeHtml(element.textContent || "");
1175
- }
1176
- const tag = tagNameOf(element).toLowerCase();
1177
- if (isCodeTextElement(tag)) {
1178
- return DEV ? `<!--ssr:${tag}-stripped-->` : "";
1179
- }
1180
- if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
1181
- return DEV ? "<!--ssr:invalid-tag-->" : "";
1182
- }
1183
- const openTag = serializeOpenTag(element, tag);
1184
- if (openTag === null) return DEV ? `<!--ssr:${tag}-stripped-->` : "";
1185
- let html2 = openTag;
1186
- if (VOID_ELEMENTS.has(tag)) {
1187
- return `${html2} />`;
1188
- }
1189
- html2 += ">";
1190
- for (const child of Array.from(childNodesOf(element))) {
1385
+ const frame = serializeNode(element, context);
1386
+ if (typeof frame === "string") return frame;
1387
+ let html2 = frame.open;
1388
+ for (const child of frame.children) {
1191
1389
  try {
1192
- html2 += renderToString(child);
1390
+ html2 += renderNodeToString(child, frame.context);
1193
1391
  } catch (err) {
1194
1392
  html2 += ssrErrorComment(err);
1195
1393
  }
1196
1394
  }
1197
- html2 += `</${tag}>`;
1198
- return html2;
1395
+ return html2 + frame.close;
1199
1396
  }
1200
1397
  function hydrate(component, container, options = {}) {
1201
1398
  const clientTree = component();
@@ -1378,56 +1575,34 @@ function renderToDocument(component, options = {}) {
1378
1575
  </body>
1379
1576
  </html>`;
1380
1577
  }
1381
- async function* renderToStream(element) {
1578
+ function renderToStream(element) {
1579
+ return streamNode(element, 0 /* Html */);
1580
+ }
1581
+ async function* streamNode(element, context) {
1382
1582
  if (element instanceof DocumentFragment) {
1383
1583
  for (const child of Array.from(element.childNodes)) {
1384
1584
  try {
1385
- yield* renderToStream(child);
1585
+ yield* streamNode(child, context);
1386
1586
  } catch (err) {
1387
1587
  yield ssrErrorComment(err);
1388
1588
  }
1389
1589
  }
1390
1590
  return;
1391
1591
  }
1392
- if (element.nodeType === 3) {
1393
- yield escapeHtml(element.textContent || "");
1394
- return;
1395
- }
1396
- if (element.nodeType === 8) {
1397
- yield `<!--${safeCommentText(element.textContent || "")}-->`;
1398
- return;
1399
- }
1400
- if (!(element instanceof HTMLElement)) {
1401
- yield escapeHtml(element.textContent || "");
1402
- return;
1403
- }
1404
- const tag = tagNameOf(element).toLowerCase();
1405
- if (isCodeTextElement(tag)) {
1406
- if (DEV) yield `<!--ssr:${tag}-stripped-->`;
1407
- return;
1408
- }
1409
- if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
1410
- if (DEV) yield "<!--ssr:invalid-tag-->";
1411
- return;
1412
- }
1413
- const openTag = serializeOpenTag(element, tag);
1414
- if (openTag === null) {
1415
- if (DEV) yield `<!--ssr:${tag}-stripped-->`;
1592
+ const frame = serializeNode(element, context);
1593
+ if (typeof frame === "string") {
1594
+ if (frame) yield frame;
1416
1595
  return;
1417
1596
  }
1418
- if (VOID_ELEMENTS.has(tag)) {
1419
- yield `${openTag} />`;
1420
- return;
1421
- }
1422
- yield `${openTag}>`;
1423
- for (const child of Array.from(childNodesOf(element))) {
1597
+ yield frame.open;
1598
+ for (const child of frame.children) {
1424
1599
  try {
1425
- yield* renderToStream(child);
1600
+ yield* streamNode(child, frame.context);
1426
1601
  } catch (err) {
1427
1602
  yield ssrErrorComment(err);
1428
1603
  }
1429
1604
  }
1430
- yield `</${tag}>`;
1605
+ yield frame.close;
1431
1606
  }
1432
1607
  async function collectStream(stream) {
1433
1608
  let result = "";
@@ -1583,8 +1758,8 @@ async function* renderToSuspenseStream(element, pendingBoundaries = [], options)
1583
1758
  function escapeScriptJson(json) {
1584
1759
  return json.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
1585
1760
  }
1586
- function serializeState(state2, nonce, options) {
1587
- const rawJson = JSON.stringify(state2);
1761
+ function serializeState(state3, nonce, options) {
1762
+ const rawJson = JSON.stringify(state3);
1588
1763
  const maxBytes = options?.maxBytes ?? DEFAULT_MAX_SSR_BYTES;
1589
1764
  const byteLen = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(rawJson).byteLength : Buffer.byteLength(rawJson, "utf8");
1590
1765
  if (byteLen > maxBytes) {
@@ -1612,7 +1787,7 @@ function escapeHtml(str) {
1612
1787
  function escapeAttr(str) {
1613
1788
  return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1614
1789
  }
1615
- var SAFE_ATTR_NAME, VOID_ELEMENTS, nativeAccessorsByRealm, SAFE_ID, SAFE_SUSPENSE_ID, SSR_DATA_ATTR, DEFAULT_MAX_SSR_BYTES;
1790
+ var SAFE_ATTR_NAME, VOID_ELEMENTS, nativeAccessorsByRealm, SVG_NS4, MATHML_NS, XLINK_NS2, XML_NS2, XMLNS_NS, BREAKOUT_TAGS, SAFE_ID, SAFE_SUSPENSE_ID, SSR_DATA_ATTR, DEFAULT_MAX_SSR_BYTES;
1616
1791
  var init_ssr = __esm({
1617
1792
  "src/platform/ssr.ts"() {
1618
1793
  "use strict";
@@ -1620,6 +1795,7 @@ var init_ssr = __esm({
1620
1795
  init_dispose();
1621
1796
  init_ssr_context();
1622
1797
  init_elementPolicy();
1798
+ init_embedPolicy();
1623
1799
  init_guards();
1624
1800
  init_headEntry();
1625
1801
  init_metaRefresh();
@@ -1642,6 +1818,57 @@ var init_ssr = __esm({
1642
1818
  "wbr"
1643
1819
  ]);
1644
1820
  nativeAccessorsByRealm = /* @__PURE__ */ new WeakMap();
1821
+ SVG_NS4 = "http://www.w3.org/2000/svg";
1822
+ MATHML_NS = "http://www.w3.org/1998/Math/MathML";
1823
+ XLINK_NS2 = "http://www.w3.org/1999/xlink";
1824
+ XML_NS2 = "http://www.w3.org/XML/1998/namespace";
1825
+ XMLNS_NS = "http://www.w3.org/2000/xmlns/";
1826
+ BREAKOUT_TAGS = /* @__PURE__ */ new Set([
1827
+ "b",
1828
+ "big",
1829
+ "blockquote",
1830
+ "body",
1831
+ "br",
1832
+ "center",
1833
+ "code",
1834
+ "dd",
1835
+ "div",
1836
+ "dl",
1837
+ "dt",
1838
+ "em",
1839
+ "embed",
1840
+ "h1",
1841
+ "h2",
1842
+ "h3",
1843
+ "h4",
1844
+ "h5",
1845
+ "h6",
1846
+ "head",
1847
+ "hr",
1848
+ "i",
1849
+ "img",
1850
+ "li",
1851
+ "listing",
1852
+ "menu",
1853
+ "meta",
1854
+ "nobr",
1855
+ "ol",
1856
+ "p",
1857
+ "pre",
1858
+ "ruby",
1859
+ "s",
1860
+ "small",
1861
+ "span",
1862
+ "strong",
1863
+ "strike",
1864
+ "sub",
1865
+ "sup",
1866
+ "table",
1867
+ "tt",
1868
+ "u",
1869
+ "ul",
1870
+ "var"
1871
+ ]);
1645
1872
  SAFE_ID = /^[A-Za-z0-9_-]+$/;
1646
1873
  SAFE_SUSPENSE_ID = /^[A-Za-z0-9_-]+$/;
1647
1874
  SSR_DATA_ATTR = "__SIBU_SSR_DATA__";
@@ -2381,7 +2608,7 @@ function forEachSubscriber(signal2, visit) {
2381
2608
  }
2382
2609
 
2383
2610
  // src/reactivity/track.ts
2384
- var _runtimeVersion = true ? "4.11.0" : "dev";
2611
+ var _runtimeVersion = true ? "4.12.0" : "dev";
2385
2612
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
2386
2613
  function resolveReactiveApi() {
2387
2614
  const g2 = globalThis;
@@ -2641,6 +2868,16 @@ function bindChildNode(placeholder, getter) {
2641
2868
  init_elementPolicy();
2642
2869
  init_sanitize();
2643
2870
  init_dispose();
2871
+
2872
+ // src/core/rendering/requireDocument.ts
2873
+ init_dev();
2874
+ function noDocument() {
2875
+ throw new Error(
2876
+ "[SibuJS] renderToString needs a DOM: register happy-dom or jsdom globals first." + (DEV ? ' There is no global `document`, and SibuJS builds live DOM nodes, on the server too. For example: import { GlobalRegistrator } from "@happy-dom/global-registrator"; GlobalRegistrator.register(); See SSR in AGENTS.md \xA710.' : "")
2877
+ );
2878
+ }
2879
+
2880
+ // src/core/rendering/tagFactory.ts
2644
2881
  var SVG_NS3 = "http://www.w3.org/2000/svg";
2645
2882
  var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
2646
2883
  "config",
@@ -2833,6 +3070,7 @@ function tagFactory(tag, ns) {
2833
3070
  if (blocked) {
2834
3071
  throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
2835
3072
  }
3073
+ if (typeof document === "undefined") noDocument();
2836
3074
  const el = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
2837
3075
  if (first === void 0) return el;
2838
3076
  if (typeof first === "string") {
@@ -3137,7 +3375,7 @@ function emitDevtools(hook, event, payload) {
3137
3375
  // src/core/signals/signal.ts
3138
3376
  var _g = globalThis;
3139
3377
  function signal(initial, options) {
3140
- const state2 = {
3378
+ const state3 = {
3141
3379
  value: initial,
3142
3380
  __v: 0,
3143
3381
  __sc: 0,
@@ -3150,71 +3388,64 @@ function signal(initial, options) {
3150
3388
  };
3151
3389
  const debugName = DEV ? options?.name : void 0;
3152
3390
  const equalsFn = options?.equals;
3153
- if (debugName) state2.__name = debugName;
3391
+ if (debugName) state3.__name = debugName;
3154
3392
  function get() {
3155
- recordDependency2(state2);
3156
- return state2.value;
3393
+ recordDependency2(state3);
3394
+ return state3.value;
3157
3395
  }
3158
- get.__signal = state2;
3396
+ get.__signal = state3;
3159
3397
  if (debugName) get.__name = debugName;
3160
3398
  let set;
3161
3399
  if (equalsFn) {
3162
3400
  set = (next) => {
3163
- const prev = state2.value;
3401
+ const prev = state3.value;
3164
3402
  const newValue = typeof next === "function" ? next(prev) : next;
3165
3403
  if (equalsFn(prev, newValue)) return;
3166
- state2.value = newValue;
3167
- state2.__v++;
3404
+ state3.value = newValue;
3405
+ state3.__v++;
3168
3406
  if (DEV) {
3169
3407
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
3170
- if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
3408
+ if (hook) emitDevtools(hook, "signal:update", { signal: state3, name: debugName, oldValue: prev, newValue });
3171
3409
  }
3172
- if (!enqueueBatchedSignal(state2)) {
3173
- notifySubscribers2(state2);
3410
+ if (!enqueueBatchedSignal(state3)) {
3411
+ notifySubscribers2(state3);
3174
3412
  }
3175
3413
  };
3176
3414
  } else if (DEV) {
3177
3415
  set = (next) => {
3178
- const prev = state2.value;
3416
+ const prev = state3.value;
3179
3417
  const newValue = typeof next === "function" ? next(prev) : next;
3180
3418
  if (Object.is(newValue, prev)) return;
3181
- state2.value = newValue;
3182
- state2.__v++;
3419
+ state3.value = newValue;
3420
+ state3.__v++;
3183
3421
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
3184
- if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
3185
- if (!enqueueBatchedSignal(state2)) {
3186
- notifySubscribers2(state2);
3422
+ if (hook) emitDevtools(hook, "signal:update", { signal: state3, name: debugName, oldValue: prev, newValue });
3423
+ if (!enqueueBatchedSignal(state3)) {
3424
+ notifySubscribers2(state3);
3187
3425
  }
3188
3426
  };
3189
3427
  } else {
3190
3428
  set = (next) => {
3191
- const prev = state2.value;
3429
+ const prev = state3.value;
3192
3430
  const newValue = typeof next === "function" ? next(prev) : next;
3193
3431
  if (Object.is(newValue, prev)) return;
3194
- state2.value = newValue;
3195
- state2.__v++;
3196
- if (!enqueueBatchedSignal(state2)) {
3197
- notifySubscribers2(state2);
3432
+ state3.value = newValue;
3433
+ state3.__v++;
3434
+ if (!enqueueBatchedSignal(state3)) {
3435
+ notifySubscribers2(state3);
3198
3436
  }
3199
3437
  };
3200
3438
  }
3201
3439
  if (DEV) {
3202
3440
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
3203
- if (hook) emitDevtools(hook, "signal:create", { signal: state2, name: debugName, getter: get, initial });
3441
+ if (hook) emitDevtools(hook, "signal:create", { signal: state3, name: debugName, getter: get, initial });
3204
3442
  }
3205
3443
  return [get, set];
3206
3444
  }
3207
3445
 
3208
3446
  // src/plugins/i18n.ts
3209
3447
  init_ssr_context();
3210
-
3211
- // src/utils/globalSingleton.ts
3212
- function globalSingleton(key, create) {
3213
- const g2 = globalThis;
3214
- return g2[key] ?? (g2[key] = create());
3215
- }
3216
-
3217
- // src/plugins/i18n.ts
3448
+ init_globalSingleton();
3218
3449
  var _i18n = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.i18n.v1"), () => ({
3219
3450
  locale: signal("en"),
3220
3451
  locales: /* @__PURE__ */ Object.create(null),
@@ -4352,7 +4583,9 @@ var _SibuRouter = class _SibuRouter {
4352
4583
  }
4353
4584
  updateHistory(to, options) {
4354
4585
  const search = serializeQuery(to.queryAll);
4355
- const fullPath = this.options.base + to.path + (search ? `?${search}` : "") + (to.hash ? `#${to.hash}` : "");
4586
+ const routeUrl = to.path + (search ? `?${search}` : "") + (to.hash ? `#${to.hash}` : "");
4587
+ const loc = globalThis.location;
4588
+ const fullPath = this.options.mode === "hash" ? `${loc ? loc.pathname + loc.search : ""}#${routeUrl}` : this.options.base + routeUrl;
4356
4589
  const h = globalThis.history;
4357
4590
  if (!h) return;
4358
4591
  if (options.replace) {
@@ -5127,7 +5360,7 @@ function RouterLink(props, children) {
5127
5360
  const targetPath = normalizePathname(hrefPathRaw);
5128
5361
  const targetQuery = queryIdentity(hrefQueryRaw);
5129
5362
  const link2 = document.createElement("a");
5130
- link2.href = href;
5363
+ link2.href = kind === "internal" && _routerRef.current["options"].mode === "hash" ? `#${href}` : href;
5131
5364
  if (target) {
5132
5365
  link2.target = target;
5133
5366
  if (target === "_blank") {
@@ -5675,7 +5908,7 @@ function renderRouteToString(url, routes, _options) {
5675
5908
  };
5676
5909
  }
5677
5910
  function renderRouteToDocument(url, routes, options) {
5678
- const { html: html2, state: state2 } = renderRouteToString(url, routes, options);
5911
+ const { html: html2, state: state3 } = renderRouteToString(url, routes, options);
5679
5912
  const opts = options || {};
5680
5913
  const metaTags = (opts.meta || []).map((attrs) => serializeHeadEntry("meta", attrs)).filter(Boolean).join("\n ");
5681
5914
  const linkTags = (opts.links || []).map((attrs) => serializeHeadEntry("link", attrs)).filter(Boolean).join("\n ");
@@ -5684,7 +5917,7 @@ function renderRouteToDocument(url, routes, options) {
5684
5917
  if (!safe) return "";
5685
5918
  return `<script src="${escapeAttrLocal(safe)}"></script>`;
5686
5919
  }).filter(Boolean).join("\n ");
5687
- const stateScript = serializeRouteState(state2, opts.nonce);
5920
+ const stateScript = serializeRouteState(state3, opts.nonce);
5688
5921
  return `<!DOCTYPE html>
5689
5922
  <html>
5690
5923
  <head>
@@ -5702,8 +5935,8 @@ function renderRouteToDocument(url, routes, options) {
5702
5935
  </body>
5703
5936
  </html>`;
5704
5937
  }
5705
- function serializeRouteState(state2, nonce) {
5706
- const json = escapeScriptJson(JSON.stringify(state2));
5938
+ function serializeRouteState(state3, nonce) {
5939
+ const json = escapeScriptJson(JSON.stringify(state3));
5707
5940
  const nonceAttr = nonce ? ` nonce="${escapeAttrLocal(nonce)}"` : "";
5708
5941
  return `<script${nonceAttr}>window.${SSR_ROUTE_STATE_KEY}=${json}</script>`;
5709
5942
  }
@@ -5782,6 +6015,7 @@ function adoptThenable(value) {
5782
6015
  }
5783
6016
 
5784
6017
  // src/plugins/plugin.ts
6018
+ init_globalSingleton();
5785
6019
  var CANCELLED_BRAND = /* @__PURE__ */ Symbol.for("sibujs.plugins.installCancelled.v1");
5786
6020
  var _a;
5787
6021
  var PluginInstallCancelledError = class extends Error {
@@ -6148,7 +6382,7 @@ var CDN_ENTRY_POINTS = {
6148
6382
  };
6149
6383
  var packageInfo = {
6150
6384
  name: "sibujs",
6151
- version: true ? "4.11.0" : "dev",
6385
+ version: true ? "4.12.0" : "dev",
6152
6386
  entryPoints: MODULE_ENTRY_POINTS,
6153
6387
  /**
6154
6388
  * Generate the package.json `exports` map. Module entries resolve to the
@@ -6293,7 +6527,8 @@ var env = {
6293
6527
  };
6294
6528
 
6295
6529
  // src/plugins/versioning.ts
6296
- var VERSION = true ? "4.11.0" : "dev";
6530
+ init_globalSingleton();
6531
+ var VERSION = true ? "4.12.0" : "dev";
6297
6532
  var NUM = "(?:0|[1-9]\\d*)";
6298
6533
  var PRE_ID = `(?:${NUM}|\\d*[a-zA-Z-][0-9a-zA-Z-]*)`;
6299
6534
  var BUILD_ID = "[0-9a-zA-Z-]+";
@@ -1,6 +1,6 @@
1
1
  import { A as Accessor } from './signal-EotCj4hS.cjs';
2
2
  import { C as Component$1, N as NodeChildren } from './types-CJFViL6Q.cjs';
3
- import { T as TrustedHTML } from './ssr-C8hgIAw7.cjs';
3
+ import { T as TrustedHTML } from './ssr-Db0Sgdu3.cjs';
4
4
  export { P as PluginContext, a as PluginInstallCancelledError, b as PluginRegistry, S as SibuPlugin, c as createPlugin, d as createPluginRegistry, i as inject, e as isPluginInstallCancelledError, p as plugin, r as resetPlugins, s as setDefaultPluginRegistry, t as triggerPluginError, f as triggerPluginMount, g as triggerPluginUnmount } from './plugin-DVgSnTfK.cjs';
5
5
  export { L as LazyModule, M as Migration, a as MigrationStorageError, P as PackageExportTarget, S as SemVer, V as VERSION, b as bundlerMetadata, c as checkCompatibility, d as compareSemVer, e as createBootSequence, f as createBundle, g as createMigrationRunner, h as createModuleRegistry, i as createSSRCache, j as createTestHarness, k as deferNonCritical, l as env, m as healthCheck, n as lazyModule, p as packageInfo, o as parseSemVer, q as preloadCritical, r as prerenderRoutes, s as satisfies } from './startup-BLfSeL15.cjs';
6
6