nodality 1.0.146 → 1.0.148

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 (94) hide show
  1. package/layout/animator.js +1 -1
  2. package/layout/audio.js +1 -1
  3. package/layout/audionew.js +1 -1
  4. package/layout/base-2.js +1 -1
  5. package/layout/base.js +1 -1
  6. package/layout/beta-desktop-bar.js +1 -1
  7. package/layout/beta-mobile-bar.js +1 -1
  8. package/layout/box.js +1 -1
  9. package/layout/button.js +1 -1
  10. package/layout/cards.js +1 -1
  11. package/layout/center.js +1 -1
  12. package/layout/checkbox.js +1 -1
  13. package/layout/circle.js +1 -1
  14. package/layout/clean-row.js +1 -1
  15. package/layout/code.js +1 -1
  16. package/layout/container.js +1 -1
  17. package/layout/custom.js +1 -1
  18. package/layout/div-image.js +1 -1
  19. package/layout/dropdown-2025.js +1 -1
  20. package/layout/dropdown.js +1 -1
  21. package/layout/empty-element.js +1 -1
  22. package/layout/external-stylesheet.js +1 -1
  23. package/layout/flex-card.js +1 -1
  24. package/layout/flex-grid.js +1 -1
  25. package/layout/flex-row.js +1 -1
  26. package/layout/footer.js +1 -1
  27. package/layout/form-components/custom.js +1 -1
  28. package/layout/form-components/data-list.js +1 -1
  29. package/layout/form-components/floating-input.js +1 -1
  30. package/layout/form-components/form-all.js +1 -1
  31. package/layout/form-components/form.js +1 -1
  32. package/layout/form-components/image-picker.js +1 -1
  33. package/layout/form-components/picker.js +1 -1
  34. package/layout/form-components/radio.js +1 -1
  35. package/layout/form-components/radiogroup.js +1 -1
  36. package/layout/form-components/range.js +1 -1
  37. package/layout/free.js +1 -1
  38. package/layout/grid-new.js +1 -1
  39. package/layout/grid-switcher.js +1 -1
  40. package/layout/grid.js +1 -1
  41. package/layout/group.js +1 -1
  42. package/layout/header.js +1 -1
  43. package/layout/horizontal-scroller.js +1 -1
  44. package/layout/image-old.js +1 -1
  45. package/layout/image.js +1 -1
  46. package/layout/index.js +1 -1
  47. package/layout/label.js +1 -1
  48. package/layout/link.js +1 -1
  49. package/layout/list-OLD.js +1 -1
  50. package/layout/list.js +1 -1
  51. package/layout/meta-adder.js +1 -1
  52. package/layout/modal-2025.js +1 -1
  53. package/layout/modernwrap.js +1 -1
  54. package/layout/multiswitcher.js +1 -1
  55. package/layout/multiswitcherBeta.js +1 -1
  56. package/layout/nav-bar.js +1 -1
  57. package/layout/nav-factor/custom-div.js +1 -1
  58. package/layout/navBar-OLD.js +1 -1
  59. package/layout/new-flat-adder.js +1 -1
  60. package/layout/new-nav-bar.js +1 -1
  61. package/layout/offset-container.js +1 -1
  62. package/layout/polygon.js +1 -1
  63. package/layout/prerender.js +85 -22
  64. package/layout/progress.js +1 -1
  65. package/layout/row.js +1 -1
  66. package/layout/saved-new-nav-bar.js +1 -1
  67. package/layout/scroll-video.js +1 -1
  68. package/layout/side-bar.js +1 -1
  69. package/layout/side-nav-bar.js +1 -1
  70. package/layout/simple-bar.js +1 -1
  71. package/layout/slider-2025.js +1 -1
  72. package/layout/spacer.js +1 -1
  73. package/layout/stack.js +1 -1
  74. package/layout/styler.js +1 -1
  75. package/layout/svg.js +1 -1
  76. package/layout/switcher.js +1 -1
  77. package/layout/table.js +1 -1
  78. package/layout/text-field.js +1 -1
  79. package/layout/text.js +1 -1
  80. package/layout/ulist.js +1 -1
  81. package/layout/video.js +1 -1
  82. package/layout/without-new.js +1 -1
  83. package/layout/wrap.js +1 -1
  84. package/layout/zoom-card.js +1 -1
  85. package/lib/card-getter.js +1 -1
  86. package/lib/designer.js +1 -1
  87. package/lib/element-mapper.js +1 -1
  88. package/lib/keyframe-animation.js +1 -1
  89. package/lib/link-getter.js +1 -1
  90. package/lib/scroll-video.js +1 -1
  91. package/lib/stacker.js +1 -1
  92. package/lib/theme.js +1 -1
  93. package/lib/transform-anim.js +1 -1
  94. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/audio.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/base-2.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/base.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/box.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/button.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/cards.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/center.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/circle.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/code.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/custom.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/footer.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/free.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/grid.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/group.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/header.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/image.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/label.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/link.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/list.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/nav-bar.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/polygon.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -93,6 +93,15 @@ import path from "node:path";
93
93
  * @param {string} [opts.url="http://localhost/"] — Base URL for the jsdom
94
94
  * window. Affects `window.location`, relative-URL resolution, and the
95
95
  * `Document.URL` your code may read.
96
+ * @param {{ width?: number, height?: number }} [opts.viewport={width:390,height:844}]
97
+ * — Simulated viewport dimensions. Drives `window.innerWidth`,
98
+ * `window.innerHeight`, and the response of `window.matchMedia()`
99
+ * to viewport queries like `(min-width: 768px)`. Default is mobile
100
+ * (iPhone 12-ish: 390×844) so JS-driven responsive layouts (e.g.
101
+ * `Switcher({ breakpoints })`) emit the MOBILE variant during SSG.
102
+ * That's the "mobile-first" pattern — phones see the right layout
103
+ * immediately, desktop users see the mobile layout briefly until
104
+ * JS rehydrates with the desktop variant.
96
105
  * @param {(window: Window) => (void | Promise<void>)} opts.build —
97
106
  * Async function that runs inside the simulated browser. Receives the
98
107
  * jsdom `window` object. Should construct the page via Nodality
@@ -110,6 +119,7 @@ export async function prerender({
110
119
  locale,
111
120
  localStorageKey = "h7lang",
112
121
  url = "http://localhost/",
122
+ viewport = { width: 390, height: 844 },
113
123
  build,
114
124
  output,
115
125
  }) {
@@ -191,18 +201,58 @@ export async function prerender({
191
201
  disconnect() {}
192
202
  };
193
203
  }
194
- if (!window.matchMedia) {
195
- window.matchMedia = () => ({
196
- matches: false,
197
- media: "",
204
+ // Simulated viewport. jsdom's defaults are 1024×768 — we override
205
+ // with the caller-provided (or default mobile) dimensions so JS-
206
+ // driven responsive layouts pick the right variant during SSG.
207
+ //
208
+ // `innerWidth` / `innerHeight` are read by code like
209
+ // `Switcher.choose()` that compares `window.innerWidth` against
210
+ // each breakpoint's `at` value. They must be defined as values
211
+ // (not getters) so subsequent assignments don't throw.
212
+ const vw = (viewport && Number(viewport.width)) || 390;
213
+ const vh = (viewport && Number(viewport.height)) || 844;
214
+ try {
215
+ Object.defineProperty(window, "innerWidth", { value: vw, configurable: true, writable: true });
216
+ Object.defineProperty(window, "innerHeight", { value: vh, configurable: true, writable: true });
217
+ Object.defineProperty(window, "outerWidth", { value: vw, configurable: true, writable: true });
218
+ Object.defineProperty(window, "outerHeight", { value: vh, configurable: true, writable: true });
219
+ } catch {
220
+ // jsdom version that freezes these — fall back to direct assignment.
221
+ try { window.innerWidth = vw; window.innerHeight = vh; } catch {}
222
+ }
223
+
224
+ // Replace jsdom's matchMedia (which returns matches:false for every
225
+ // query) with a viewport-aware shim that resolves CSS `(min-width:
226
+ // N)` / `(max-width: N)` against the simulated width. This lets
227
+ // matchMedia-driven responsive code (and Nodality's Switcher
228
+ // matchMedia path) pick the right branch during SSG.
229
+ //
230
+ // We override unconditionally — jsdom's default is too permissive
231
+ // for our purposes since it answers `false` for every viewport
232
+ // query, defeating the mobile-first goal.
233
+ window.matchMedia = (query) => {
234
+ let matches = false;
235
+ if (typeof query === "string" && query.includes("width")) {
236
+ // Parse a single "(min-width: 768px)" or "(max-width: 768px)"
237
+ // clause. Multi-clause queries (commas, `and`) fall through to
238
+ // false — Nodality's breakpoint code doesn't emit those.
239
+ const min = query.match(/min-width:\s*(\d+)\s*px/i);
240
+ const max = query.match(/max-width:\s*(\d+)\s*px/i);
241
+ if (min && !max) matches = vw >= Number(min[1]);
242
+ else if (max && !min) matches = vw <= Number(max[1]);
243
+ // Both present (range) or other → leave as false.
244
+ }
245
+ return {
246
+ matches,
247
+ media: query || "",
198
248
  onchange: null,
199
249
  addListener() {},
200
250
  removeListener() {},
201
251
  addEventListener() {},
202
252
  removeEventListener() {},
203
253
  dispatchEvent() { return false; },
204
- });
205
- }
254
+ };
255
+ };
206
256
  // Some libraries probe these for code-splitting / analytics. Stub
207
257
  // them as harmless no-ops so the builder doesn't crash; the live
208
258
  // browser still uses the real implementations.
@@ -240,22 +290,23 @@ export async function prerender({
240
290
  // since jsdom provides its own copy on `window` that the builder
241
291
  // can reach via `window.navigator`. Same defensive check for any
242
292
  // other future getter-only globals Node may add.
293
+ // Rather than try to detect every read-only global ahead of time
294
+ // (descriptors differ subtly between data and accessor properties,
295
+ // and Node's set keeps evolving), just attempt each assignment in
296
+ // a try/catch and remember which ones actually took. The finally
297
+ // block only restores the successful ones, preventing the same
298
+ // throw on cleanup.
243
299
  const originalGlobals = {};
300
+ const assigned = new Set();
244
301
  for (const key of PROXIED) {
245
- if (key in globalThis) originalGlobals[key] = globalThis[key];
246
302
  if (!(key in window)) continue;
247
- const desc = Object.getOwnPropertyDescriptor(globalThis, key);
248
- if (desc && desc.set === undefined && desc.writable === false) {
249
- // Read-only built-in (e.g. Node 22+ `navigator`). Skip — the
250
- // builder can still reach the jsdom copy via `window.<key>`.
251
- continue;
252
- }
253
303
  try {
304
+ if (key in globalThis) originalGlobals[key] = globalThis[key];
254
305
  globalThis[key] = window[key];
306
+ assigned.add(key);
255
307
  } catch {
256
- // Belt-and-braces: if descriptor inspection missed something
257
- // (host-defined exotic, frozen prototype chain), swallow the
258
- // assignment failure rather than aborting the whole render.
308
+ // Read-only built-in (e.g. Node 22+ `navigator`). The builder
309
+ // can still reach the jsdom copy via `window.<key>`.
259
310
  }
260
311
  }
261
312
 
@@ -303,11 +354,23 @@ export async function prerender({
303
354
  // caller runs prerender() in a loop — without this, the second
304
355
  // invocation would inherit the FIRST jsdom's window, which has
305
356
  // already been closed.
306
- for (const key of PROXIED) {
307
- if (key in originalGlobals) {
308
- globalThis[key] = originalGlobals[key];
309
- } else {
310
- delete globalThis[key];
357
+ //
358
+ // We only restore keys we successfully wrote in the first place
359
+ // (`assigned`). Anything Node refused to let us assign is still
360
+ // its original built-in, so there's nothing to roll back. Each
361
+ // restore is also try/catch-guarded for the same reason — if
362
+ // Node tightened the descriptor between begin and end of build
363
+ // (unlikely but cheap to defend against), we want cleanup to
364
+ // continue rather than throw out of the finally block.
365
+ for (const key of assigned) {
366
+ try {
367
+ if (key in originalGlobals) {
368
+ globalThis[key] = originalGlobals[key];
369
+ } else {
370
+ delete globalThis[key];
371
+ }
372
+ } catch {
373
+ // Skip — restoration is best-effort.
311
374
  }
312
375
  }
313
376
  // Release jsdom's internal resources (timers, parser state).
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/row.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/spacer.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/stack.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/styler.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/svg.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/table.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/text.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/ulist.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/video.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/layout/wrap.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/designer.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/stacker.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/lib/theme.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * nodality v1.0.146
2
+ * nodality v1.0.148
3
3
  * (c) 2026 Filip Vabrousek
4
4
  * License: MIT
5
5
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodality",
3
- "version": "1.0.146",
3
+ "version": "1.0.148",
4
4
  "description": "A lightweight library for declarative UI elements.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",