sibujs 1.0.0 → 1.0.2

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 (52) hide show
  1. package/dist/browser.js +4 -3
  2. package/dist/build.cjs +11 -3
  3. package/dist/build.js +10 -9
  4. package/dist/cdn.global.js +4 -4
  5. package/dist/chunk-24WSRM54.js +2002 -0
  6. package/dist/chunk-3CRQALYP.js +877 -0
  7. package/dist/chunk-6HLLIF3K.js +398 -0
  8. package/dist/chunk-7TQKR4PP.js +294 -0
  9. package/dist/chunk-CZUGLNJS.js +37 -0
  10. package/dist/chunk-DTCOOBMX.js +725 -0
  11. package/dist/chunk-FGOEVHY3.js +60 -0
  12. package/dist/chunk-HGMJFBC7.js +654 -0
  13. package/dist/chunk-HS6OOE3Q.js +365 -0
  14. package/dist/chunk-L36YN45V.js +949 -0
  15. package/dist/chunk-MJ4LVHGX.js +712 -0
  16. package/dist/chunk-N6IZB6KJ.js +567 -0
  17. package/dist/chunk-NMRUZALC.js +1097 -0
  18. package/dist/chunk-OHQQWZ7P.js +969 -0
  19. package/dist/chunk-ONCYDOK6.js +466 -0
  20. package/dist/chunk-OWLQ4HZI.js +282 -0
  21. package/dist/chunk-PZEGYCF5.js +61 -0
  22. package/dist/chunk-QVKGGB2S.js +300 -0
  23. package/dist/chunk-SDLZDHKP.js +107 -0
  24. package/dist/chunk-Y6GP4QGG.js +276 -0
  25. package/dist/chunk-YECR7UIA.js +347 -0
  26. package/dist/chunk-Z65KYU7I.js +26 -0
  27. package/dist/data.cjs +24 -4
  28. package/dist/data.js +6 -5
  29. package/dist/devtools.cjs +1 -1
  30. package/dist/devtools.js +4 -3
  31. package/dist/ecosystem.cjs +9 -2
  32. package/dist/ecosystem.js +7 -6
  33. package/dist/extras.cjs +68 -24
  34. package/dist/extras.js +21 -20
  35. package/dist/index.cjs +11 -3
  36. package/dist/index.js +10 -9
  37. package/dist/motion.js +3 -2
  38. package/dist/patterns.cjs +7 -2
  39. package/dist/patterns.d.cts +15 -0
  40. package/dist/patterns.d.ts +15 -0
  41. package/dist/patterns.js +5 -4
  42. package/dist/performance.js +3 -2
  43. package/dist/plugins.cjs +65 -29
  44. package/dist/plugins.js +9 -8
  45. package/dist/ssr-WKUPVSSK.js +36 -0
  46. package/dist/ssr.cjs +60 -41
  47. package/dist/ssr.d.cts +9 -3
  48. package/dist/ssr.d.ts +9 -3
  49. package/dist/ssr.js +8 -7
  50. package/dist/ui.js +6 -5
  51. package/dist/widgets.js +5 -4
  52. package/package.json +1 -1
package/dist/patterns.cjs CHANGED
@@ -414,10 +414,13 @@ function persisted(key, initial, options = {}) {
414
414
  const storage = options.session ? sessionStorage : localStorage;
415
415
  const serialize = options.serialize || JSON.stringify;
416
416
  const deserialize = options.deserialize || JSON.parse;
417
+ const encrypt = options.encrypt;
418
+ const decrypt = options.decrypt;
417
419
  let restored = initial;
418
420
  try {
419
- const raw = storage.getItem(key);
421
+ let raw = storage.getItem(key);
420
422
  if (raw !== null) {
423
+ if (decrypt) raw = decrypt(raw);
421
424
  const parsed = deserialize(raw);
422
425
  restored = options.validate && !options.validate(parsed) ? initial : parsed;
423
426
  }
@@ -427,7 +430,9 @@ function persisted(key, initial, options = {}) {
427
430
  effect(() => {
428
431
  const current = value();
429
432
  try {
430
- storage.setItem(key, serialize(current));
433
+ let serialized = serialize(current);
434
+ if (encrypt) serialized = encrypt(serialized);
435
+ storage.setItem(key, serialized);
431
436
  } catch {
432
437
  }
433
438
  });
@@ -54,6 +54,21 @@ interface PersistOptions<T = unknown> {
54
54
  deserialize?: (raw: string) => unknown;
55
55
  /** Optional type guard to validate deserialized data. Falls back to initial on failure. */
56
56
  validate?: (value: unknown) => value is T;
57
+ /**
58
+ * Encrypt the serialized value before writing to storage.
59
+ * Paired with `decrypt` for reading. Use for sensitive data.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * persisted("token", "", {
64
+ * encrypt: (v) => btoa(v), // or use Web Crypto API
65
+ * decrypt: (v) => atob(v),
66
+ * });
67
+ * ```
68
+ */
69
+ encrypt?: (value: string) => string;
70
+ /** Decrypt the stored value before deserialization. Required if `encrypt` is set. */
71
+ decrypt?: (value: string) => string;
57
72
  }
58
73
  declare function persisted<T>(key: string, initial: T, options?: PersistOptions<T>): [() => T, (next: T | ((prev: T) => T)) => void];
59
74
 
@@ -54,6 +54,21 @@ interface PersistOptions<T = unknown> {
54
54
  deserialize?: (raw: string) => unknown;
55
55
  /** Optional type guard to validate deserialized data. Falls back to initial on failure. */
56
56
  validate?: (value: unknown) => value is T;
57
+ /**
58
+ * Encrypt the serialized value before writing to storage.
59
+ * Paired with `decrypt` for reading. Use for sensitive data.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * persisted("token", "", {
64
+ * encrypt: (v) => btoa(v), // or use Web Crypto API
65
+ * decrypt: (v) => atob(v),
66
+ * });
67
+ * ```
68
+ */
69
+ encrypt?: (value: string) => string;
70
+ /** Decrypt the stored value before deserialization. Required if `encrypt` is set. */
71
+ decrypt?: (value: string) => string;
57
72
  }
58
73
  declare function persisted<T>(key: string, initial: T, options?: PersistOptions<T>): [() => T, (next: T | ((prev: T) => T)) => void];
59
74
 
package/dist/patterns.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  optimisticList,
9
9
  persisted,
10
10
  timeline
11
- } from "./chunk-BWBWJYBK.js";
11
+ } from "./chunk-Y6GP4QGG.js";
12
12
  import {
13
13
  RenderProp,
14
14
  assertType,
@@ -26,10 +26,11 @@ import {
26
26
  withProps,
27
27
  withWrapper
28
28
  } from "./chunk-XYU6TZOW.js";
29
- import "./chunk-SU63HSUU.js";
30
- import "./chunk-OZS4YOOP.js";
29
+ import "./chunk-FGOEVHY3.js";
30
+ import "./chunk-PZEGYCF5.js";
31
31
  import "./chunk-CHJ27IGK.js";
32
- import "./chunk-KKUV25KB.js";
32
+ import "./chunk-YECR7UIA.js";
33
+ import "./chunk-4MYMUBRS.js";
33
34
  import "./chunk-MLKGABMK.js";
34
35
  export {
35
36
  RenderProp,
@@ -33,8 +33,9 @@ import {
33
33
  transitionState,
34
34
  uniqueId,
35
35
  yieldToMain
36
- } from "./chunk-DGUYCZJH.js";
37
- import "./chunk-KKUV25KB.js";
36
+ } from "./chunk-HGMJFBC7.js";
37
+ import "./chunk-YECR7UIA.js";
38
+ import "./chunk-4MYMUBRS.js";
38
39
  import "./chunk-MLKGABMK.js";
39
40
  export {
40
41
  DOMPool,
package/dist/plugins.cjs CHANGED
@@ -20,6 +20,28 @@ var __copyProps = (to, from, except, desc) => {
20
20
  };
21
21
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
22
 
23
+ // src/core/dev.ts
24
+ function isDev() {
25
+ return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : true;
26
+ }
27
+ function devAssert(condition, message) {
28
+ if (_isDev && !condition) {
29
+ throw new Error(`[Sibu] ${message}`);
30
+ }
31
+ }
32
+ function devWarn(message) {
33
+ if (_isDev) {
34
+ console.warn(`[Sibu] ${message}`);
35
+ }
36
+ }
37
+ var _isDev;
38
+ var init_dev = __esm({
39
+ "src/core/dev.ts"() {
40
+ "use strict";
41
+ _isDev = isDev();
42
+ }
43
+ });
44
+
23
45
  // src/platform/ssr.ts
24
46
  var ssr_exports = {};
25
47
  __export(ssr_exports, {
@@ -39,13 +61,19 @@ __export(ssr_exports, {
39
61
  ssrSuspense: () => ssrSuspense,
40
62
  suspenseSwapScript: () => suspenseSwapScript
41
63
  });
64
+ function ssrErrorComment(err) {
65
+ if (_isDev7) {
66
+ return `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
67
+ }
68
+ return "<!--SSR error-->";
69
+ }
42
70
  function renderToString(element) {
43
71
  if (element instanceof DocumentFragment) {
44
72
  return Array.from(element.childNodes).map((child) => {
45
73
  try {
46
74
  return renderToString(child);
47
75
  } catch (err) {
48
- return `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
76
+ return ssrErrorComment(err);
49
77
  }
50
78
  }).join("");
51
79
  }
@@ -75,7 +103,7 @@ function renderToString(element) {
75
103
  try {
76
104
  html2 += renderToString(child);
77
105
  } catch (err) {
78
- html2 += `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
106
+ html2 += ssrErrorComment(err);
79
107
  }
80
108
  }
81
109
  html2 += `</${tag}>`;
@@ -99,7 +127,7 @@ function renderToDocument(component, options = {}) {
99
127
  try {
100
128
  content = renderToString(component());
101
129
  } catch (err) {
102
- content = `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
130
+ content = ssrErrorComment(err);
103
131
  }
104
132
  const metaTags = (options.meta || []).map(
105
133
  (attrs) => `<meta ${Object.entries(attrs).map(([k, v]) => `${k}="${escapeAttr(v)}"`).join(" ")} />`
@@ -131,7 +159,7 @@ async function* renderToStream(element) {
131
159
  try {
132
160
  yield* renderToStream(child);
133
161
  } catch (err) {
134
- yield `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
162
+ yield ssrErrorComment(err);
135
163
  }
136
164
  }
137
165
  return;
@@ -163,7 +191,7 @@ async function* renderToStream(element) {
163
191
  try {
164
192
  yield* renderToStream(child);
165
193
  } catch (err) {
166
- yield `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
194
+ yield ssrErrorComment(err);
167
195
  }
168
196
  }
169
197
  yield `</${tag}>`;
@@ -252,9 +280,10 @@ function ssrSuspense(props) {
252
280
  }));
253
281
  return { element: wrapper, promise };
254
282
  }
255
- function suspenseSwapScript(id) {
283
+ function suspenseSwapScript(id, nonce) {
256
284
  const safeId = id.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/</g, "\\u003c").replace(/>/g, "\\u003e");
257
- return `<script>(function(){var t=document.getElementById("sibu-resolved-${safeId}");var f=document.querySelector('[data-sibu-suspense-id="${safeId}"]');if(t&&f){while(t.firstChild)f.appendChild(t.firstChild);t.remove();f.removeAttribute("data-sibu-suspense-id");}})()</script>`;
285
+ const nonceAttr = nonce ? ` nonce="${escapeAttr(nonce)}"` : "";
286
+ return `<script${nonceAttr}>(function(){var t=document.getElementById("sibu-resolved-${safeId}");var f=document.querySelector('[data-sibu-suspense-id="${safeId}"]');if(t&&f){while(t.firstChild)f.appendChild(t.firstChild);t.remove();f.removeAttribute("data-sibu-suspense-id");}})()</script>`;
258
287
  }
259
288
  async function* renderToSuspenseStream(element, pendingBoundaries = []) {
260
289
  yield* renderToStream(element);
@@ -266,13 +295,17 @@ async function* renderToSuspenseStream(element, pendingBoundaries = []) {
266
295
  }
267
296
  }
268
297
  }
269
- function serializeState(state) {
298
+ function serializeState(state, nonce) {
270
299
  const json = JSON.stringify(state).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026");
271
- return `<script>window.${SSR_DATA_ATTR}=${json}</script>`;
300
+ const nonceAttr = nonce ? ` nonce="${escapeAttr(nonce)}"` : "";
301
+ return `<script${nonceAttr}>window.${SSR_DATA_ATTR}=${json}</script>`;
272
302
  }
273
- function deserializeState() {
303
+ function deserializeState(validate) {
274
304
  if (typeof window === "undefined") return void 0;
275
- return window[SSR_DATA_ATTR];
305
+ const raw = window[SSR_DATA_ATTR];
306
+ if (raw === void 0) return void 0;
307
+ if (validate && !validate(raw)) return void 0;
308
+ return raw;
276
309
  }
277
310
  function escapeHtml(str) {
278
311
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -280,10 +313,12 @@ function escapeHtml(str) {
280
313
  function escapeAttr(str) {
281
314
  return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
282
315
  }
283
- var VOID_ELEMENTS, suspenseIdCounter, SSR_DATA_ATTR;
316
+ var _isDev7, VOID_ELEMENTS, suspenseIdCounter, SSR_DATA_ATTR;
284
317
  var init_ssr = __esm({
285
318
  "src/platform/ssr.ts"() {
286
319
  "use strict";
320
+ init_dev();
321
+ _isDev7 = isDev();
287
322
  VOID_ELEMENTS = /* @__PURE__ */ new Set([
288
323
  "area",
289
324
  "base",
@@ -382,21 +417,8 @@ __export(plugins_exports, {
382
417
  });
383
418
  module.exports = __toCommonJS(plugins_exports);
384
419
 
385
- // src/core/dev.ts
386
- function isDev() {
387
- return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : true;
388
- }
389
- var _isDev = isDev();
390
- function devAssert(condition, message) {
391
- if (_isDev && !condition) {
392
- throw new Error(`[Sibu] ${message}`);
393
- }
394
- }
395
- function devWarn(message) {
396
- if (_isDev) {
397
- console.warn(`[Sibu] ${message}`);
398
- }
399
- }
420
+ // src/reactivity/bindAttribute.ts
421
+ init_dev();
400
422
 
401
423
  // src/utils/sanitize.ts
402
424
  function sanitizeUrl(url) {
@@ -408,12 +430,20 @@ function sanitizeUrl(url) {
408
430
  }
409
431
  return trimmed;
410
432
  }
433
+ function sanitizeCSSValue(value) {
434
+ const lower = value.toLowerCase().replace(/\s+/g, "");
435
+ if (lower.includes("url(") || lower.includes("expression(") || lower.includes("javascript:") || lower.includes("-moz-binding")) {
436
+ return "";
437
+ }
438
+ return value;
439
+ }
411
440
  var URL_ATTRIBUTES = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "cite", "poster", "background", "srcset"]);
412
441
  function isUrlAttribute(attr) {
413
442
  return URL_ATTRIBUTES.has(attr);
414
443
  }
415
444
 
416
445
  // src/reactivity/track.ts
446
+ init_dev();
417
447
  var _isDev2 = isDev();
418
448
  var subscriberStack = new Array(32);
419
449
  var stackCapacity = 32;
@@ -652,6 +682,7 @@ function bindAttribute(el, attr, getter) {
652
682
  }
653
683
 
654
684
  // src/reactivity/bindChildNode.ts
685
+ init_dev();
655
686
  var _isDev4 = isDev();
656
687
  function bindChildNode(placeholder, getter) {
657
688
  let lastNodes = [];
@@ -698,6 +729,7 @@ function bindChildNode(placeholder, getter) {
698
729
  }
699
730
 
700
731
  // src/core/rendering/dispose.ts
732
+ init_dev();
701
733
  var elementDisposers = /* @__PURE__ */ new WeakMap();
702
734
  var _isDev5 = isDev();
703
735
  var activeBindingCount = 0;
@@ -740,11 +772,11 @@ function applyStyle(el, style2) {
740
772
  if (typeof val === "function") {
741
773
  const getter = val;
742
774
  const teardown = track(() => {
743
- htmlEl.style.setProperty(name, String(getter()));
775
+ htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
744
776
  });
745
777
  registerDisposer(el, teardown);
746
778
  } else {
747
- htmlEl.style.setProperty(name, String(val));
779
+ htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
748
780
  }
749
781
  }
750
782
  }
@@ -1047,6 +1079,7 @@ function enqueueBatchedSignal(signal2) {
1047
1079
  }
1048
1080
 
1049
1081
  // src/core/signals/signal.ts
1082
+ init_dev();
1050
1083
  var _g = globalThis;
1051
1084
  var _isDev6 = isDev();
1052
1085
  function signal(initial, options) {
@@ -1114,6 +1147,9 @@ function getAvailableLocales() {
1114
1147
  return Object.keys(locales);
1115
1148
  }
1116
1149
 
1150
+ // src/core/signals/effect.ts
1151
+ init_dev();
1152
+
1117
1153
  // src/core/ssr-context.ts
1118
1154
  var ssrMode = false;
1119
1155
  function isSSR() {
package/dist/plugins.js CHANGED
@@ -18,10 +18,10 @@ import {
18
18
  preloadCritical,
19
19
  prerenderRoutes,
20
20
  satisfies
21
- } from "./chunk-ANRSGGFC.js";
21
+ } from "./chunk-DTCOOBMX.js";
22
22
  import {
23
23
  renderToString
24
- } from "./chunk-UATXXETW.js";
24
+ } from "./chunk-7TQKR4PP.js";
25
25
  import {
26
26
  createPlugin,
27
27
  inject,
@@ -33,19 +33,20 @@ import {
33
33
  } from "./chunk-K5ZUMYVS.js";
34
34
  import {
35
35
  span
36
- } from "./chunk-MGYRVG2A.js";
36
+ } from "./chunk-OWLQ4HZI.js";
37
37
  import {
38
38
  registerDisposer
39
- } from "./chunk-LHNJSLC6.js";
40
- import "./chunk-NMTRH4Q3.js";
39
+ } from "./chunk-QVKGGB2S.js";
40
+ import "./chunk-SDLZDHKP.js";
41
41
  import {
42
42
  effect
43
- } from "./chunk-OZS4YOOP.js";
43
+ } from "./chunk-PZEGYCF5.js";
44
44
  import "./chunk-CHJ27IGK.js";
45
45
  import {
46
46
  signal,
47
47
  track
48
- } from "./chunk-KKUV25KB.js";
48
+ } from "./chunk-YECR7UIA.js";
49
+ import "./chunk-4MYMUBRS.js";
49
50
  import "./chunk-MLKGABMK.js";
50
51
 
51
52
  // src/plugins/i18n.ts
@@ -1473,7 +1474,7 @@ function hydrateRouter(routes, options) {
1473
1474
  if (container && serverState.path) {
1474
1475
  const resolved = resolveServerRoute(serverState.path, routes);
1475
1476
  if (resolved.component) {
1476
- import("./ssr-GEOEYQV7.js").then(({ hydrate }) => {
1477
+ import("./ssr-WKUPVSSK.js").then(({ hydrate }) => {
1477
1478
  if (resolved.component) {
1478
1479
  hydrate(resolved.component, container);
1479
1480
  }
@@ -0,0 +1,36 @@
1
+ import {
2
+ collectStream,
3
+ deserializeState,
4
+ hydrate,
5
+ hydrateIslands,
6
+ hydrateProgressively,
7
+ island,
8
+ renderToDocument,
9
+ renderToReadableStream,
10
+ renderToStream,
11
+ renderToString,
12
+ renderToSuspenseStream,
13
+ resetSSRState,
14
+ serializeState,
15
+ ssrSuspense,
16
+ suspenseSwapScript
17
+ } from "./chunk-7TQKR4PP.js";
18
+ import "./chunk-4MYMUBRS.js";
19
+ import "./chunk-MLKGABMK.js";
20
+ export {
21
+ collectStream,
22
+ deserializeState,
23
+ hydrate,
24
+ hydrateIslands,
25
+ hydrateProgressively,
26
+ island,
27
+ renderToDocument,
28
+ renderToReadableStream,
29
+ renderToStream,
30
+ renderToString,
31
+ renderToSuspenseStream,
32
+ resetSSRState,
33
+ serializeState,
34
+ ssrSuspense,
35
+ suspenseSwapScript
36
+ };
package/dist/ssr.cjs CHANGED
@@ -61,7 +61,30 @@ __export(ssr_exports, {
61
61
  });
62
62
  module.exports = __toCommonJS(ssr_exports);
63
63
 
64
+ // src/core/dev.ts
65
+ function isDev() {
66
+ return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : true;
67
+ }
68
+ var _isDev = isDev();
69
+ function devAssert(condition, message) {
70
+ if (_isDev && !condition) {
71
+ throw new Error(`[Sibu] ${message}`);
72
+ }
73
+ }
74
+ function devWarn(message) {
75
+ if (_isDev) {
76
+ console.warn(`[Sibu] ${message}`);
77
+ }
78
+ }
79
+
64
80
  // src/platform/ssr.ts
81
+ var _isDev2 = isDev();
82
+ function ssrErrorComment(err) {
83
+ if (_isDev2) {
84
+ return `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
85
+ }
86
+ return "<!--SSR error-->";
87
+ }
65
88
  var VOID_ELEMENTS = /* @__PURE__ */ new Set([
66
89
  "area",
67
90
  "base",
@@ -84,7 +107,7 @@ function renderToString(element) {
84
107
  try {
85
108
  return renderToString(child);
86
109
  } catch (err) {
87
- return `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
110
+ return ssrErrorComment(err);
88
111
  }
89
112
  }).join("");
90
113
  }
@@ -114,7 +137,7 @@ function renderToString(element) {
114
137
  try {
115
138
  html2 += renderToString(child);
116
139
  } catch (err) {
117
- html2 += `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
140
+ html2 += ssrErrorComment(err);
118
141
  }
119
142
  }
120
143
  html2 += `</${tag}>`;
@@ -138,7 +161,7 @@ function renderToDocument(component, options = {}) {
138
161
  try {
139
162
  content = renderToString(component());
140
163
  } catch (err) {
141
- content = `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
164
+ content = ssrErrorComment(err);
142
165
  }
143
166
  const metaTags = (options.meta || []).map(
144
167
  (attrs) => `<meta ${Object.entries(attrs).map(([k, v]) => `${k}="${escapeAttr(v)}"`).join(" ")} />`
@@ -170,7 +193,7 @@ async function* renderToStream(element) {
170
193
  try {
171
194
  yield* renderToStream(child);
172
195
  } catch (err) {
173
- yield `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
196
+ yield ssrErrorComment(err);
174
197
  }
175
198
  }
176
199
  return;
@@ -202,7 +225,7 @@ async function* renderToStream(element) {
202
225
  try {
203
226
  yield* renderToStream(child);
204
227
  } catch (err) {
205
- yield `<!--SSR error: ${escapeHtml(err instanceof Error ? err.message : String(err))}-->`;
228
+ yield ssrErrorComment(err);
206
229
  }
207
230
  }
208
231
  yield `</${tag}>`;
@@ -292,9 +315,10 @@ function ssrSuspense(props) {
292
315
  }));
293
316
  return { element: wrapper, promise };
294
317
  }
295
- function suspenseSwapScript(id) {
318
+ function suspenseSwapScript(id, nonce) {
296
319
  const safeId = id.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/</g, "\\u003c").replace(/>/g, "\\u003e");
297
- return `<script>(function(){var t=document.getElementById("sibu-resolved-${safeId}");var f=document.querySelector('[data-sibu-suspense-id="${safeId}"]');if(t&&f){while(t.firstChild)f.appendChild(t.firstChild);t.remove();f.removeAttribute("data-sibu-suspense-id");}})()</script>`;
320
+ const nonceAttr = nonce ? ` nonce="${escapeAttr(nonce)}"` : "";
321
+ return `<script${nonceAttr}>(function(){var t=document.getElementById("sibu-resolved-${safeId}");var f=document.querySelector('[data-sibu-suspense-id="${safeId}"]');if(t&&f){while(t.firstChild)f.appendChild(t.firstChild);t.remove();f.removeAttribute("data-sibu-suspense-id");}})()</script>`;
298
322
  }
299
323
  async function* renderToSuspenseStream(element, pendingBoundaries = []) {
300
324
  yield* renderToStream(element);
@@ -307,13 +331,17 @@ async function* renderToSuspenseStream(element, pendingBoundaries = []) {
307
331
  }
308
332
  }
309
333
  var SSR_DATA_ATTR = "__SIBU_SSR_DATA__";
310
- function serializeState(state) {
334
+ function serializeState(state, nonce) {
311
335
  const json = JSON.stringify(state).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026");
312
- return `<script>window.${SSR_DATA_ATTR}=${json}</script>`;
336
+ const nonceAttr = nonce ? ` nonce="${escapeAttr(nonce)}"` : "";
337
+ return `<script${nonceAttr}>window.${SSR_DATA_ATTR}=${json}</script>`;
313
338
  }
314
- function deserializeState() {
339
+ function deserializeState(validate) {
315
340
  if (typeof window === "undefined") return void 0;
316
- return window[SSR_DATA_ATTR];
341
+ const raw = window[SSR_DATA_ATTR];
342
+ if (raw === void 0) return void 0;
343
+ if (validate && !validate(raw)) return void 0;
344
+ return raw;
317
345
  }
318
346
  function escapeHtml(str) {
319
347
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -322,24 +350,8 @@ function escapeAttr(str) {
322
350
  return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
323
351
  }
324
352
 
325
- // src/core/dev.ts
326
- function isDev() {
327
- return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : true;
328
- }
329
- var _isDev = isDev();
330
- function devAssert(condition, message) {
331
- if (_isDev && !condition) {
332
- throw new Error(`[Sibu] ${message}`);
333
- }
334
- }
335
- function devWarn(message) {
336
- if (_isDev) {
337
- console.warn(`[Sibu] ${message}`);
338
- }
339
- }
340
-
341
353
  // src/reactivity/track.ts
342
- var _isDev2 = isDev();
354
+ var _isDev3 = isDev();
343
355
  var subscriberStack = new Array(32);
344
356
  var stackCapacity = 32;
345
357
  var stackTop = -1;
@@ -353,7 +365,7 @@ function safeInvoke(sub2) {
353
365
  try {
354
366
  sub2();
355
367
  } catch (err) {
356
- if (_isDev2) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
368
+ if (_isDev3) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
357
369
  }
358
370
  }
359
371
  function track(effectFn, subscriber) {
@@ -616,6 +628,13 @@ function sanitizeUrl(url) {
616
628
  }
617
629
  return trimmed;
618
630
  }
631
+ function sanitizeCSSValue(value) {
632
+ const lower = value.toLowerCase().replace(/\s+/g, "");
633
+ if (lower.includes("url(") || lower.includes("expression(") || lower.includes("javascript:") || lower.includes("-moz-binding")) {
634
+ return "";
635
+ }
636
+ return value;
637
+ }
619
638
  var URL_ATTRIBUTES = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "cite", "poster", "background", "srcset"]);
620
639
  function isUrlAttribute(attr) {
621
640
  return URL_ATTRIBUTES.has(attr);
@@ -768,10 +787,10 @@ function flushBatch() {
768
787
 
769
788
  // src/core/signals/signal.ts
770
789
  var _g2 = globalThis;
771
- var _isDev3 = isDev();
790
+ var _isDev4 = isDev();
772
791
  function signal(initial, options) {
773
792
  const state = { value: initial };
774
- const debugName = _isDev3 ? options?.name : void 0;
793
+ const debugName = _isDev4 ? options?.name : void 0;
775
794
  const equalsFn = options?.equals;
776
795
  if (debugName) {
777
796
  state.__name = debugName;
@@ -785,7 +804,7 @@ function signal(initial, options) {
785
804
  function set(next) {
786
805
  const newValue = typeof next === "function" ? next(state.value) : next;
787
806
  if (equalsFn ? equalsFn(state.value, newValue) : Object.is(newValue, state.value)) return;
788
- if (_isDev3) {
807
+ if (_isDev4) {
789
808
  const oldValue = state.value;
790
809
  state.value = newValue;
791
810
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
@@ -797,7 +816,7 @@ function signal(initial, options) {
797
816
  notifySubscribers(state);
798
817
  }
799
818
  }
800
- if (_isDev3) {
819
+ if (_isDev4) {
801
820
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
802
821
  if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
803
822
  }
@@ -933,14 +952,14 @@ function createMiddlewareChain() {
933
952
  }
934
953
 
935
954
  // src/reactivity/bindAttribute.ts
936
- var _isDev4 = isDev();
955
+ var _isDev5 = isDev();
937
956
  function bindAttribute(el, attr, getter) {
938
957
  function commit() {
939
958
  let value;
940
959
  try {
941
960
  value = getter();
942
961
  } catch (err) {
943
- if (_isDev4)
962
+ if (_isDev5)
944
963
  devWarn(`bindAttribute: getter for "${attr}" threw: ${err instanceof Error ? err.message : String(err)}`);
945
964
  return;
946
965
  }
@@ -966,7 +985,7 @@ function bindAttribute(el, attr, getter) {
966
985
  }
967
986
 
968
987
  // src/reactivity/bindChildNode.ts
969
- var _isDev5 = isDev();
988
+ var _isDev6 = isDev();
970
989
  function bindChildNode(placeholder, getter) {
971
990
  let lastNodes = [];
972
991
  function commit() {
@@ -974,7 +993,7 @@ function bindChildNode(placeholder, getter) {
974
993
  try {
975
994
  result = getter();
976
995
  } catch (err) {
977
- if (_isDev5) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
996
+ if (_isDev6) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
978
997
  return;
979
998
  }
980
999
  for (let i2 = 0; i2 < lastNodes.length; i2++) {
@@ -1013,7 +1032,7 @@ function bindChildNode(placeholder, getter) {
1013
1032
 
1014
1033
  // src/core/rendering/dispose.ts
1015
1034
  var elementDisposers = /* @__PURE__ */ new WeakMap();
1016
- var _isDev6 = isDev();
1035
+ var _isDev7 = isDev();
1017
1036
  var activeBindingCount = 0;
1018
1037
  function registerDisposer(node, teardown) {
1019
1038
  let disposers = elementDisposers.get(node);
@@ -1022,7 +1041,7 @@ function registerDisposer(node, teardown) {
1022
1041
  elementDisposers.set(node, disposers);
1023
1042
  }
1024
1043
  disposers.push(teardown);
1025
- if (_isDev6) activeBindingCount++;
1044
+ if (_isDev7) activeBindingCount++;
1026
1045
  }
1027
1046
 
1028
1047
  // src/core/rendering/tagFactory.ts
@@ -1054,11 +1073,11 @@ function applyStyle(el, style2) {
1054
1073
  if (typeof val === "function") {
1055
1074
  const getter = val;
1056
1075
  const teardown = track(() => {
1057
- htmlEl.style.setProperty(name, String(getter()));
1076
+ htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
1058
1077
  });
1059
1078
  registerDisposer(el, teardown);
1060
1079
  } else {
1061
- htmlEl.style.setProperty(name, String(val));
1080
+ htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
1062
1081
  }
1063
1082
  }
1064
1083
  }