meno-core 1.0.53 → 1.0.54

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 (387) hide show
  1. package/.claude/settings.local.json +1 -3
  2. package/bin/cli.ts +48 -57
  3. package/build-astro.ts +131 -113
  4. package/build-next.ts +109 -96
  5. package/build-static.test.ts +39 -10
  6. package/build-static.ts +120 -122
  7. package/dist/bin/cli.js +34 -38
  8. package/dist/bin/cli.js.map +2 -2
  9. package/dist/build-static.js +12 -11
  10. package/dist/chunks/chunk-2AR55GYH.js +42 -0
  11. package/dist/chunks/chunk-2AR55GYH.js.map +7 -0
  12. package/dist/chunks/{chunk-IGYR22T6.js → chunk-2FN4UOVO.js} +512 -239
  13. package/dist/chunks/chunk-2FN4UOVO.js.map +7 -0
  14. package/dist/chunks/chunk-3XER4E5W.js +168 -0
  15. package/dist/chunks/chunk-3XER4E5W.js.map +7 -0
  16. package/dist/chunks/{chunk-X754AHS5.js → chunk-5ETZFREW.js} +9 -12
  17. package/dist/chunks/chunk-5ETZFREW.js.map +7 -0
  18. package/dist/chunks/{chunk-2MHDV5BF.js → chunk-7E4IF5L7.js} +15 -21
  19. package/dist/chunks/chunk-7E4IF5L7.js.map +7 -0
  20. package/dist/chunks/{chunk-JGWFTO6P.js → chunk-7HWQUVTU.js} +1578 -1349
  21. package/dist/chunks/chunk-7HWQUVTU.js.map +7 -0
  22. package/dist/chunks/{chunk-O3NAGJP4.js → chunk-AE3QK5QW.js} +110 -21
  23. package/dist/chunks/chunk-AE3QK5QW.js.map +7 -0
  24. package/dist/chunks/{chunk-GZHGVVW3.js → chunk-F6KTJYGV.js} +7 -7
  25. package/dist/chunks/chunk-F6KTJYGV.js.map +7 -0
  26. package/dist/chunks/{chunk-WQFG7PAH.js → chunk-FZITJSSS.js} +2 -6
  27. package/dist/chunks/chunk-FZITJSSS.js.map +7 -0
  28. package/dist/chunks/{chunk-QB2LNO4W.js → chunk-GSYYA5GX.js} +2 -2
  29. package/dist/chunks/chunk-GSYYA5GX.js.map +7 -0
  30. package/dist/chunks/{chunk-YBLHKYFF.js → chunk-HIZMY3EP.js} +1 -1
  31. package/dist/chunks/chunk-HIZMY3EP.js.map +7 -0
  32. package/dist/chunks/{chunk-AZQYF6KE.js → chunk-I2WEGYA7.js} +41 -176
  33. package/dist/chunks/chunk-I2WEGYA7.js.map +7 -0
  34. package/dist/chunks/{chunk-I7YIGZXT.js → chunk-JNO3CNLJ.js} +6 -9
  35. package/dist/chunks/chunk-JNO3CNLJ.js.map +7 -0
  36. package/dist/chunks/{chunk-UB44F4Z2.js → chunk-NVRBTSQG.js} +2 -4
  37. package/dist/chunks/chunk-NVRBTSQG.js.map +7 -0
  38. package/dist/chunks/{chunk-JGP5A3Y5.js → chunk-Q4OBWKXG.js} +40 -33
  39. package/dist/chunks/chunk-Q4OBWKXG.js.map +7 -0
  40. package/dist/chunks/{chunk-R6XHAFBF.js → chunk-QTE32Y53.js} +250 -242
  41. package/dist/chunks/chunk-QTE32Y53.js.map +7 -0
  42. package/dist/chunks/{chunk-H3GJ4H2U.js → chunk-STDY3OVM.js} +214 -85
  43. package/dist/chunks/chunk-STDY3OVM.js.map +7 -0
  44. package/dist/chunks/configService-PRJZF7Y6.js +14 -0
  45. package/dist/chunks/{constants-STK2YBIW.js → constants-KIQEYMAM.js} +2 -2
  46. package/dist/chunks/{fs-JGINUXGL.js → fs-ZI5JEU7V.js} +2 -2
  47. package/dist/entries/server-router.js +14 -19
  48. package/dist/entries/server-router.js.map +2 -2
  49. package/dist/lib/client/index.js +638 -332
  50. package/dist/lib/client/index.js.map +2 -2
  51. package/dist/lib/server/index.js +177 -235
  52. package/dist/lib/server/index.js.map +2 -2
  53. package/dist/lib/shared/index.js +80 -44
  54. package/dist/lib/shared/index.js.map +2 -2
  55. package/dist/lib/shared/richtext/index.js +1 -1
  56. package/dist/lib/test-utils/index.js +38 -60
  57. package/dist/lib/test-utils/index.js.map +2 -2
  58. package/entries/client-router.tsx +10 -8
  59. package/entries/server-router.tsx +1 -7
  60. package/lib/client/ClientInitializer.ts +8 -8
  61. package/lib/client/ErrorBoundary.test.tsx +146 -143
  62. package/lib/client/ErrorBoundary.tsx +175 -127
  63. package/lib/client/componentRegistry.test.ts +96 -108
  64. package/lib/client/componentRegistry.ts +1 -2
  65. package/lib/client/contexts/ThemeContext.tsx +3 -2
  66. package/lib/client/core/ComponentBuilder.test.ts +513 -560
  67. package/lib/client/core/ComponentBuilder.ts +318 -146
  68. package/lib/client/core/ComponentRenderer.test.tsx +1 -2
  69. package/lib/client/core/ComponentRenderer.tsx +46 -33
  70. package/lib/client/core/builders/embedBuilder.ts +241 -53
  71. package/lib/client/core/builders/linkBuilder.ts +71 -44
  72. package/lib/client/core/builders/linkNodeBuilder.ts +78 -53
  73. package/lib/client/core/builders/listBuilder.ts +115 -86
  74. package/lib/client/core/builders/localeListBuilder.ts +95 -60
  75. package/lib/client/core/builders/types.ts +5 -5
  76. package/lib/client/core/cmsTemplateProcessor.ts +7 -7
  77. package/lib/client/elementRegistry.ts +3 -3
  78. package/lib/client/fontFamiliesService.test.ts +2 -10
  79. package/lib/client/fontFamiliesService.ts +3 -3
  80. package/lib/client/hmr/HMRManager.tsx +8 -0
  81. package/lib/client/hmrCssReload.ts +14 -8
  82. package/lib/client/hmrWebSocket.ts +9 -14
  83. package/lib/client/hooks/useColorVariables.test.ts +21 -21
  84. package/lib/client/hooks/useColorVariables.ts +12 -10
  85. package/lib/client/hooks/usePropertyAutocomplete.ts +3 -5
  86. package/lib/client/hooks/useVariables.ts +4 -4
  87. package/lib/client/hydration/HydrationUtils.test.ts +24 -25
  88. package/lib/client/hydration/HydrationUtils.ts +3 -4
  89. package/lib/client/i18nConfigService.test.ts +2 -7
  90. package/lib/client/i18nConfigService.ts +2 -2
  91. package/lib/client/meno-filter/MenoFilter.test.ts +19 -21
  92. package/lib/client/meno-filter/MenoFilter.ts +5 -9
  93. package/lib/client/meno-filter/bindings.ts +15 -40
  94. package/lib/client/meno-filter/init.ts +1 -1
  95. package/lib/client/meno-filter/renderer.ts +23 -29
  96. package/lib/client/meno-filter/script.generated.ts +1 -3
  97. package/lib/client/meno-filter/ui.ts +3 -5
  98. package/lib/client/meno-filter/updates.ts +15 -21
  99. package/lib/client/navigation.test.ts +159 -159
  100. package/lib/client/navigation.ts +0 -1
  101. package/lib/client/responsiveStyleResolver.test.ts +230 -228
  102. package/lib/client/responsiveStyleResolver.ts +13 -16
  103. package/lib/client/routing/RouteLoader.test.ts +23 -24
  104. package/lib/client/routing/RouteLoader.ts +22 -35
  105. package/lib/client/routing/Router.tsx +31 -3
  106. package/lib/client/scripts/ScriptExecutor.test.ts +157 -158
  107. package/lib/client/scripts/ScriptExecutor.ts +15 -33
  108. package/lib/client/services/PrefetchService.test.ts +2 -2
  109. package/lib/client/services/PrefetchService.ts +10 -24
  110. package/lib/client/styleProcessor.test.ts +9 -9
  111. package/lib/client/styleProcessor.ts +18 -15
  112. package/lib/client/styles/StyleInjector.test.ts +122 -115
  113. package/lib/client/styles/StyleInjector.ts +9 -6
  114. package/lib/client/styles/UtilityClassCollector.ts +19 -26
  115. package/lib/client/styles/cspNonce.test.ts +2 -5
  116. package/lib/client/templateEngine.test.ts +554 -482
  117. package/lib/client/templateEngine.ts +200 -64
  118. package/lib/client/theme.ts +0 -1
  119. package/lib/client/utils/toast.ts +0 -1
  120. package/lib/server/__integration__/api-routes.test.ts +8 -4
  121. package/lib/server/__integration__/cms-integration.test.ts +1 -4
  122. package/lib/server/__integration__/server-lifecycle.test.ts +2 -5
  123. package/lib/server/__integration__/ssr-rendering.test.ts +47 -37
  124. package/lib/server/__integration__/static-assets.test.ts +1 -1
  125. package/lib/server/__integration__/test-helpers.ts +84 -70
  126. package/lib/server/ab/generateFunctions.ts +12 -10
  127. package/lib/server/astro/cmsPageEmitter.ts +23 -38
  128. package/lib/server/astro/componentEmitter.ts +25 -36
  129. package/lib/server/astro/cssCollector.ts +10 -26
  130. package/lib/server/astro/nodeToAstro.test.ts +1750 -30
  131. package/lib/server/astro/nodeToAstro.ts +198 -187
  132. package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +105 -109
  133. package/lib/server/astro/normalizeOrphanTemplateProps.ts +4 -12
  134. package/lib/server/astro/pageEmitter.ts +9 -13
  135. package/lib/server/astro/tailwindMapper.test.ts +10 -37
  136. package/lib/server/astro/tailwindMapper.ts +33 -40
  137. package/lib/server/astro/templateTransformer.ts +14 -17
  138. package/lib/server/createServer.ts +5 -17
  139. package/lib/server/cssGenerator.test.ts +35 -44
  140. package/lib/server/cssGenerator.ts +6 -17
  141. package/lib/server/fileWatcher.test.ts +124 -10
  142. package/lib/server/fileWatcher.ts +124 -118
  143. package/lib/server/index.ts +7 -1
  144. package/lib/server/jsonLoader.test.ts +39 -2
  145. package/lib/server/jsonLoader.ts +33 -31
  146. package/lib/server/middleware/cors.test.ts +20 -20
  147. package/lib/server/middleware/cors.ts +28 -4
  148. package/lib/server/middleware/errorHandler.test.ts +5 -3
  149. package/lib/server/middleware/errorHandler.ts +3 -8
  150. package/lib/server/middleware/index.ts +0 -1
  151. package/lib/server/middleware/logger.test.ts +7 -5
  152. package/lib/server/middleware/logger.ts +10 -22
  153. package/lib/server/pageCache.test.ts +76 -77
  154. package/lib/server/pageCache.ts +0 -1
  155. package/lib/server/projectContext.ts +4 -3
  156. package/lib/server/providers/fileSystemCMSProvider.test.ts +124 -95
  157. package/lib/server/providers/fileSystemCMSProvider.ts +35 -20
  158. package/lib/server/providers/fileSystemPageProvider.test.ts +84 -0
  159. package/lib/server/providers/fileSystemPageProvider.ts +31 -12
  160. package/lib/server/routes/api/cms.test.ts +26 -14
  161. package/lib/server/routes/api/cms.ts +9 -14
  162. package/lib/server/routes/api/components.ts +30 -34
  163. package/lib/server/routes/api/config.ts +0 -1
  164. package/lib/server/routes/api/core-routes.ts +47 -74
  165. package/lib/server/routes/api/functions.ts +8 -16
  166. package/lib/server/routes/api/index.ts +3 -6
  167. package/lib/server/routes/api/pages.ts +8 -11
  168. package/lib/server/routes/api/shared.test.ts +1 -1
  169. package/lib/server/routes/api/shared.ts +12 -9
  170. package/lib/server/routes/api/variables.test.ts +1 -3
  171. package/lib/server/routes/api/variables.ts +1 -1
  172. package/lib/server/routes/index.ts +23 -26
  173. package/lib/server/routes/pages.ts +34 -29
  174. package/lib/server/routes/static.ts +16 -4
  175. package/lib/server/runtime/bundler.ts +47 -32
  176. package/lib/server/runtime/fs.ts +3 -13
  177. package/lib/server/runtime/httpServer.ts +5 -9
  178. package/lib/server/services/ColorService.ts +32 -27
  179. package/lib/server/services/EnumService.test.ts +2 -6
  180. package/lib/server/services/EnumService.ts +7 -2
  181. package/lib/server/services/VariableService.test.ts +1 -5
  182. package/lib/server/services/VariableService.ts +6 -1
  183. package/lib/server/services/cmsService.test.ts +116 -78
  184. package/lib/server/services/cmsService.ts +24 -54
  185. package/lib/server/services/componentService.test.ts +122 -36
  186. package/lib/server/services/componentService.ts +54 -38
  187. package/lib/server/services/configService.test.ts +9 -31
  188. package/lib/server/services/configService.ts +20 -27
  189. package/lib/server/services/fileWatcherService.ts +40 -6
  190. package/lib/server/services/index.ts +0 -1
  191. package/lib/server/services/pageService.test.ts +1 -3
  192. package/lib/server/services/pageService.ts +14 -13
  193. package/lib/server/ssr/attributeBuilder.ts +16 -6
  194. package/lib/server/ssr/buildErrorOverlay.ts +11 -12
  195. package/lib/server/ssr/clientDataInjector.ts +7 -21
  196. package/lib/server/ssr/cmsSSRProcessor.ts +3 -6
  197. package/lib/server/ssr/cssCollector.ts +1 -1
  198. package/lib/server/ssr/errorOverlay.test.ts +1 -1
  199. package/lib/server/ssr/errorOverlay.ts +3 -9
  200. package/lib/server/ssr/htmlGenerator.nonce.test.ts +3 -9
  201. package/lib/server/ssr/htmlGenerator.test.ts +120 -43
  202. package/lib/server/ssr/htmlGenerator.ts +120 -85
  203. package/lib/server/ssr/imageMetadata.test.ts +3 -1
  204. package/lib/server/ssr/imageMetadata.ts +25 -19
  205. package/lib/server/ssr/jsCollector.test.ts +3 -13
  206. package/lib/server/ssr/jsCollector.ts +3 -8
  207. package/lib/server/ssr/liveReloadIntegration.test.ts +69 -28
  208. package/lib/server/ssr/metaTagGenerator.ts +2 -2
  209. package/lib/server/ssr/ssrRenderer.branches.test.ts +1103 -0
  210. package/lib/server/ssr/ssrRenderer.test.ts +196 -246
  211. package/lib/server/ssr/ssrRenderer.ts +609 -225
  212. package/lib/server/ssrRenderer.test.ts +1044 -950
  213. package/lib/server/utils/jsonLineMapper.test.ts +28 -28
  214. package/lib/server/utils/jsonLineMapper.ts +1 -1
  215. package/lib/server/validateStyleCoverage.ts +18 -20
  216. package/lib/server/webflow/buildWebflow.ts +41 -53
  217. package/lib/server/webflow/nodeToWebflow.test.ts +150 -218
  218. package/lib/server/webflow/nodeToWebflow.ts +195 -258
  219. package/lib/server/webflow/styleMapper.test.ts +15 -56
  220. package/lib/server/webflow/styleMapper.ts +33 -41
  221. package/lib/server/webflow/types.ts +1 -8
  222. package/lib/server/websocketManager.ts +16 -19
  223. package/lib/shared/attributeNodeUtils.test.ts +15 -15
  224. package/lib/shared/attributeNodeUtils.ts +5 -12
  225. package/lib/shared/breakpoints.ts +4 -11
  226. package/lib/shared/cmsQueryParser.test.ts +50 -42
  227. package/lib/shared/cmsQueryParser.ts +49 -31
  228. package/lib/shared/colorVariableUtils.test.ts +5 -5
  229. package/lib/shared/colorVariableUtils.ts +3 -8
  230. package/lib/shared/componentRefs.ts +1 -5
  231. package/lib/shared/constants.test.ts +3 -3
  232. package/lib/shared/constants.ts +4 -8
  233. package/lib/shared/cssGeneration.test.ts +262 -144
  234. package/lib/shared/cssGeneration.ts +189 -516
  235. package/lib/shared/cssNamedColors.ts +152 -30
  236. package/lib/shared/cssProperties.test.ts +5 -6
  237. package/lib/shared/cssProperties.ts +296 -112
  238. package/lib/shared/elementClassName.test.ts +109 -109
  239. package/lib/shared/elementClassName.ts +1 -1
  240. package/lib/shared/elementUtils.ts +12 -16
  241. package/lib/shared/errorLogger.ts +2 -10
  242. package/lib/shared/errors.test.ts +2 -13
  243. package/lib/shared/errors.ts +2 -8
  244. package/lib/shared/expressionEvaluator.test.ts +119 -0
  245. package/lib/shared/expressionEvaluator.ts +43 -24
  246. package/lib/shared/fontLoader.test.ts +19 -5
  247. package/lib/shared/friendlyError.ts +2 -3
  248. package/lib/shared/gradientUtils.test.ts +1 -5
  249. package/lib/shared/gradientUtils.ts +2 -6
  250. package/lib/shared/hrefRefs.ts +2 -10
  251. package/lib/shared/i18n.test.ts +1 -1
  252. package/lib/shared/i18n.ts +13 -34
  253. package/lib/shared/index.ts +4 -0
  254. package/lib/shared/inlineSvgStyleRules.ts +2 -4
  255. package/lib/shared/interactiveStyleMappings.test.ts +11 -33
  256. package/lib/shared/interactiveStyleMappings.ts +9 -16
  257. package/lib/shared/interactiveStyles.test.ts +165 -188
  258. package/lib/shared/interfaces/contentProvider.ts +1 -1
  259. package/lib/shared/itemTemplateUtils.test.ts +6 -12
  260. package/lib/shared/itemTemplateUtils.ts +19 -35
  261. package/lib/shared/jsonRepair.ts +8 -2
  262. package/lib/shared/libraryLoader.test.ts +15 -49
  263. package/lib/shared/libraryLoader.ts +7 -22
  264. package/lib/shared/netlifyLocale404.test.ts +179 -0
  265. package/lib/shared/netlifyLocale404.ts +110 -0
  266. package/lib/shared/nodeUtils.test.ts +24 -16
  267. package/lib/shared/nodeUtils.ts +49 -19
  268. package/lib/shared/pathArrayUtils.test.ts +1 -2
  269. package/lib/shared/pathArrayUtils.ts +1 -1
  270. package/lib/shared/pathSecurity.ts +1 -1
  271. package/lib/shared/pathUtils.test.ts +4 -6
  272. package/lib/shared/pathUtils.ts +42 -48
  273. package/lib/shared/paths/Path.test.ts +2 -2
  274. package/lib/shared/paths/Path.ts +0 -1
  275. package/lib/shared/paths/PathConverter.test.ts +1 -1
  276. package/lib/shared/paths/PathConverter.ts +14 -17
  277. package/lib/shared/paths/PathUtils.ts +9 -10
  278. package/lib/shared/paths/PathValidator.test.ts +2 -15
  279. package/lib/shared/paths/PathValidator.ts +11 -9
  280. package/lib/shared/paths/index.ts +1 -2
  281. package/lib/shared/propResolver.test.ts +240 -244
  282. package/lib/shared/propResolver.ts +14 -25
  283. package/lib/shared/pxToRem.test.ts +7 -6
  284. package/lib/shared/pxToRem.ts +2 -5
  285. package/lib/shared/registry/BaseNodeTypeRegistry.test.ts +9 -5
  286. package/lib/shared/registry/ClientRegistry.ts +0 -1
  287. package/lib/shared/registry/ComponentRegistry.test.ts +43 -29
  288. package/lib/shared/registry/ComponentRegistry.ts +9 -11
  289. package/lib/shared/registry/NodeTypeDefinition.ts +15 -8
  290. package/lib/shared/registry/RegistryManager.ts +1 -2
  291. package/lib/shared/registry/SSRRegistry.ts +0 -1
  292. package/lib/shared/registry/createNodeType.ts +7 -9
  293. package/lib/shared/registry/defineNodeType.ts +2 -6
  294. package/lib/shared/registry/index.ts +0 -1
  295. package/lib/shared/registry/nodeTypes/ComponentInstanceNodeType.ts +14 -15
  296. package/lib/shared/registry/nodeTypes/EmbedNodeType.ts +18 -11
  297. package/lib/shared/registry/nodeTypes/HtmlNodeType.ts +47 -18
  298. package/lib/shared/registry/nodeTypes/LinkNodeType.ts +21 -19
  299. package/lib/shared/registry/nodeTypes/ListNodeType.ts +78 -74
  300. package/lib/shared/registry/nodeTypes/LocaleListNodeType.ts +27 -21
  301. package/lib/shared/registry/nodeTypes/SlotMarkerType.ts +6 -7
  302. package/lib/shared/registry/nodeTypes/index.ts +10 -2
  303. package/lib/shared/responsiveScaling.test.ts +15 -31
  304. package/lib/shared/responsiveScaling.ts +55 -37
  305. package/lib/shared/responsiveStyleUtils.ts +11 -13
  306. package/lib/shared/richtext/htmlToTiptap.test.ts +23 -14
  307. package/lib/shared/richtext/htmlToTiptap.ts +1 -3
  308. package/lib/shared/richtext/tiptapToHtml.test.ts +5 -6
  309. package/lib/shared/richtext/types.ts +1 -8
  310. package/lib/shared/slugTranslator.test.ts +13 -13
  311. package/lib/shared/slugTranslator.ts +12 -16
  312. package/lib/shared/slugify.ts +9 -15
  313. package/lib/shared/styleNodeUtils.test.ts +8 -8
  314. package/lib/shared/styleNodeUtils.ts +5 -10
  315. package/lib/shared/styleUtils.test.ts +87 -61
  316. package/lib/shared/styleUtils.ts +5 -6
  317. package/lib/shared/themeDefaults.test.ts +11 -11
  318. package/lib/shared/themeDefaults.ts +3 -4
  319. package/lib/shared/tree/PathBuilder.test.ts +62 -138
  320. package/lib/shared/tree/PathBuilder.ts +49 -39
  321. package/lib/shared/treePathUtils.test.ts +2 -10
  322. package/lib/shared/treePathUtils.ts +54 -59
  323. package/lib/shared/types/api.ts +1 -2
  324. package/lib/shared/types/cms.ts +25 -21
  325. package/lib/shared/types/comment.ts +49 -16
  326. package/lib/shared/types/components.ts +27 -25
  327. package/lib/shared/types/errors.test.ts +1 -6
  328. package/lib/shared/types/errors.ts +3 -7
  329. package/lib/shared/types/experiments.ts +28 -28
  330. package/lib/shared/types/index.ts +2 -2
  331. package/lib/shared/types/styles.ts +0 -1
  332. package/lib/shared/types/variables.test.ts +4 -13
  333. package/lib/shared/types/variables.ts +48 -27
  334. package/lib/shared/types.ts +1 -2
  335. package/lib/shared/utilityClassConfig.ts +648 -321
  336. package/lib/shared/utilityClassMapper.test.ts +203 -92
  337. package/lib/shared/utilityClassMapper.ts +188 -246
  338. package/lib/shared/utilityClassNames.ts +326 -0
  339. package/lib/shared/utils.test.ts +2 -10
  340. package/lib/shared/utils.ts +19 -10
  341. package/lib/shared/validation/cmsValidators.ts +2 -1
  342. package/lib/shared/validation/commentValidators.test.ts +53 -0
  343. package/lib/shared/validation/commentValidators.ts +12 -1
  344. package/lib/shared/validation/propValidator.test.ts +18 -20
  345. package/lib/shared/validation/propValidator.ts +12 -17
  346. package/lib/shared/validation/schemas.test.ts +24 -33
  347. package/lib/shared/validation/schemas.ts +469 -344
  348. package/lib/shared/validation/validators.test.ts +1 -6
  349. package/lib/shared/validation/validators.ts +89 -68
  350. package/lib/shared/viewportUnits.integration.test.ts +14 -10
  351. package/lib/shared/viewportUnits.test.ts +11 -23
  352. package/lib/test-utils/dom-setup.ts +1 -1
  353. package/lib/test-utils/factories/ConsoleMockFactory.ts +3 -7
  354. package/lib/test-utils/factories/DomMockFactory.ts +7 -19
  355. package/lib/test-utils/factories/EventMockFactory.ts +7 -13
  356. package/lib/test-utils/factories/FetchMockFactory.ts +39 -57
  357. package/lib/test-utils/factories/ServerMockFactory.ts +5 -9
  358. package/lib/test-utils/factories/StoreMockFactory.ts +14 -25
  359. package/lib/test-utils/fixtures.ts +45 -45
  360. package/lib/test-utils/helpers/asyncHelpers.test.ts +15 -18
  361. package/lib/test-utils/helpers/asyncHelpers.ts +11 -20
  362. package/lib/test-utils/helpers.ts +1 -5
  363. package/lib/test-utils/index.ts +0 -4
  364. package/lib/test-utils/mockFactories.ts +12 -18
  365. package/lib/test-utils/mocks.ts +4 -2
  366. package/package.json +1 -1
  367. package/scripts/build-meno-filter.ts +1 -4
  368. package/vite.config.ts +4 -4
  369. package/dist/chunks/chunk-2MHDV5BF.js.map +0 -7
  370. package/dist/chunks/chunk-AZQYF6KE.js.map +0 -7
  371. package/dist/chunks/chunk-GZHGVVW3.js.map +0 -7
  372. package/dist/chunks/chunk-H3GJ4H2U.js.map +0 -7
  373. package/dist/chunks/chunk-I7YIGZXT.js.map +0 -7
  374. package/dist/chunks/chunk-IGYR22T6.js.map +0 -7
  375. package/dist/chunks/chunk-JGP5A3Y5.js.map +0 -7
  376. package/dist/chunks/chunk-JGWFTO6P.js.map +0 -7
  377. package/dist/chunks/chunk-O3NAGJP4.js.map +0 -7
  378. package/dist/chunks/chunk-QB2LNO4W.js.map +0 -7
  379. package/dist/chunks/chunk-R6XHAFBF.js.map +0 -7
  380. package/dist/chunks/chunk-UB44F4Z2.js.map +0 -7
  381. package/dist/chunks/chunk-WQFG7PAH.js.map +0 -7
  382. package/dist/chunks/chunk-X754AHS5.js.map +0 -7
  383. package/dist/chunks/chunk-YBLHKYFF.js.map +0 -7
  384. package/dist/chunks/configService-R3OGU2UD.js +0 -13
  385. /package/dist/chunks/{configService-R3OGU2UD.js.map → configService-PRJZF7Y6.js.map} +0 -0
  386. /package/dist/chunks/{constants-STK2YBIW.js.map → constants-KIQEYMAM.js.map} +0 -0
  387. /package/dist/chunks/{fs-JGINUXGL.js.map → fs-ZI5JEU7V.js.map} +0 -0
@@ -12,21 +12,20 @@ import { createNodeType } from '../createNodeType';
12
12
  const ComponentNodeSchemaRef: z.ZodType<any> = z.lazy(() => z.any());
13
13
 
14
14
  // Schema is the SINGLE source of truth
15
- const ComponentInstanceNodeSchemaInternal = z.object({
16
- type: z.literal('component'),
17
- component: z.string(),
18
- label: z.string().optional(), // Custom label displayed in structure tree
19
- if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
20
- props: z.record(z.string(), z.any()).optional(),
21
- style: StyleValueSchema.optional(),
22
- interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
23
- generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
24
- attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
25
- children: z.union([
26
- z.array(z.union([ComponentNodeSchemaRef, z.string()])),
27
- z.string(),
28
- ]).optional(),
29
- }).passthrough();
15
+ const ComponentInstanceNodeSchemaInternal = z
16
+ .object({
17
+ type: z.literal('component'),
18
+ component: z.string(),
19
+ label: z.string().optional(), // Custom label displayed in structure tree
20
+ if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
21
+ props: z.record(z.string(), z.any()).optional(),
22
+ style: StyleValueSchema.optional(),
23
+ interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
24
+ generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
25
+ attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
26
+ children: z.union([z.array(z.union([ComponentNodeSchemaRef, z.string()])), z.string()]).optional(),
27
+ })
28
+ .passthrough();
30
29
 
31
30
  // TypeScript type inferred from schema
32
31
  export type ComponentInstanceNode = z.infer<typeof ComponentInstanceNodeSchemaInternal>;
@@ -5,21 +5,28 @@
5
5
 
6
6
  import { z } from 'zod';
7
7
  import { createElement as h } from 'react';
8
- import { StyleValueSchema, InteractiveStylesSchema, IfConditionSchema, HtmlMappingSchema } from '../../validation/schemas';
8
+ import {
9
+ StyleValueSchema,
10
+ InteractiveStylesSchema,
11
+ IfConditionSchema,
12
+ HtmlMappingSchema,
13
+ } from '../../validation/schemas';
9
14
  import { createNodeType } from '../createNodeType';
10
15
  import { textareaField } from '../fieldPresets';
11
16
 
12
17
  // Schema is the SINGLE source of truth
13
- const EmbedNodeSchemaInternal = z.object({
14
- type: z.literal('embed'),
15
- html: z.union([z.string(), HtmlMappingSchema]),
16
- label: z.string().optional(), // Custom label displayed in structure tree
17
- if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
18
- style: StyleValueSchema.optional(),
19
- interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
20
- generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
21
- attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
22
- }).passthrough();
18
+ const EmbedNodeSchemaInternal = z
19
+ .object({
20
+ type: z.literal('embed'),
21
+ html: z.union([z.string(), HtmlMappingSchema]),
22
+ label: z.string().optional(), // Custom label displayed in structure tree
23
+ if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
24
+ style: StyleValueSchema.optional(),
25
+ interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
26
+ generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
27
+ attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
28
+ })
29
+ .passthrough();
23
30
 
24
31
  // TypeScript type inferred from schema
25
32
  export type EmbedNode = z.infer<typeof EmbedNodeSchemaInternal>;
@@ -12,21 +12,20 @@ import { createNodeType } from '../createNodeType';
12
12
  const ComponentNodeSchemaRef: z.ZodType<any> = z.lazy(() => z.any());
13
13
 
14
14
  // Schema is the SINGLE source of truth
15
- const HtmlNodeSchemaInternal = z.object({
16
- type: z.literal('node'),
17
- tag: z.string(),
18
- label: z.string().optional(), // Custom label displayed in structure tree
19
- if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
20
- style: StyleValueSchema.optional(),
21
- interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
22
- generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
23
- attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
24
- props: z.record(z.string(), z.any()).optional(), // Backward compatibility
25
- children: z.union([
26
- z.array(z.union([ComponentNodeSchemaRef, z.string()])),
27
- z.string(),
28
- ]).optional(),
29
- }).passthrough();
15
+ const HtmlNodeSchemaInternal = z
16
+ .object({
17
+ type: z.literal('node'),
18
+ tag: z.string(),
19
+ label: z.string().optional(), // Custom label displayed in structure tree
20
+ if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
21
+ style: StyleValueSchema.optional(),
22
+ interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
23
+ generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
24
+ attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
25
+ props: z.record(z.string(), z.any()).optional(), // Backward compatibility
26
+ children: z.union([z.array(z.union([ComponentNodeSchemaRef, z.string()])), z.string()]).optional(),
27
+ })
28
+ .passthrough();
30
29
 
31
30
  // TypeScript type inferred from schema
32
31
  export type HtmlNode = z.infer<typeof HtmlNodeSchemaInternal>;
@@ -60,7 +59,22 @@ export const HtmlNodeType = createNodeType({
60
59
  }
61
60
 
62
61
  // Void elements cannot have children
63
- const voidElements = ['img', 'br', 'hr', 'input', 'meta', 'link', 'area', 'base', 'col', 'embed', 'param', 'source', 'track', 'wbr'];
62
+ const voidElements = [
63
+ 'img',
64
+ 'br',
65
+ 'hr',
66
+ 'input',
67
+ 'meta',
68
+ 'link',
69
+ 'area',
70
+ 'base',
71
+ 'col',
72
+ 'embed',
73
+ 'param',
74
+ 'source',
75
+ 'track',
76
+ 'wbr',
77
+ ];
64
78
  if (voidElements.includes(node.tag.toLowerCase())) {
65
79
  return h(node.tag, props);
66
80
  }
@@ -69,7 +83,7 @@ export const HtmlNodeType = createNodeType({
69
83
  node.children as any,
70
84
  context.elementPath,
71
85
  context.parentComponentName,
72
- context.componentContext
86
+ context.componentContext,
73
87
  );
74
88
 
75
89
  return h(node.tag, props, children);
@@ -78,7 +92,22 @@ export const HtmlNodeType = createNodeType({
78
92
  ssrRenderer: (node, context) => {
79
93
  const childrenHTML = context.renderChildren(node.children as any, context);
80
94
  // Void elements don't have closing tags
81
- const voidElements = ['img', 'br', 'hr', 'input', 'meta', 'link', 'area', 'base', 'col', 'embed', 'param', 'source', 'track', 'wbr'];
95
+ const voidElements = [
96
+ 'img',
97
+ 'br',
98
+ 'hr',
99
+ 'input',
100
+ 'meta',
101
+ 'link',
102
+ 'area',
103
+ 'base',
104
+ 'col',
105
+ 'embed',
106
+ 'param',
107
+ 'source',
108
+ 'track',
109
+ 'wbr',
110
+ ];
82
111
  if (voidElements.includes(node.tag.toLowerCase())) {
83
112
  return `<${node.tag} />`;
84
113
  }
@@ -5,7 +5,12 @@
5
5
 
6
6
  import { z } from 'zod';
7
7
  import { createElement as h } from 'react';
8
- import { StyleValueSchema, InteractiveStylesSchema, LinkMappingSchema, IfConditionSchema } from '../../validation/schemas';
8
+ import {
9
+ StyleValueSchema,
10
+ InteractiveStylesSchema,
11
+ LinkMappingSchema,
12
+ IfConditionSchema,
13
+ } from '../../validation/schemas';
9
14
  import { createNodeType } from '../createNodeType';
10
15
  import { urlField } from '../fieldPresets';
11
16
 
@@ -14,20 +19,19 @@ import { urlField } from '../fieldPresets';
14
19
  const ComponentNodeSchemaRef: z.ZodType<any> = z.lazy(() => z.any());
15
20
 
16
21
  // Schema is the SINGLE source of truth
17
- const LinkNodeSchemaInternal = z.object({
18
- type: z.literal('link'),
19
- href: z.union([z.string(), LinkMappingSchema]),
20
- label: z.string().optional(), // Custom label displayed in structure tree
21
- if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
22
- style: StyleValueSchema.optional(),
23
- interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
24
- generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
25
- attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
26
- children: z.union([
27
- z.array(z.union([ComponentNodeSchemaRef, z.string()])),
28
- z.string(),
29
- ]).optional(),
30
- }).passthrough();
22
+ const LinkNodeSchemaInternal = z
23
+ .object({
24
+ type: z.literal('link'),
25
+ href: z.union([z.string(), LinkMappingSchema]),
26
+ label: z.string().optional(), // Custom label displayed in structure tree
27
+ if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
28
+ style: StyleValueSchema.optional(),
29
+ interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
30
+ generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
31
+ attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
32
+ children: z.union([z.array(z.union([ComponentNodeSchemaRef, z.string()])), z.string()]).optional(),
33
+ })
34
+ .passthrough();
31
35
 
32
36
  // TypeScript type inferred from schema
33
37
  export type LinkNode = z.infer<typeof LinkNodeSchemaInternal>;
@@ -52,16 +56,14 @@ export const LinkNodeType = createNodeType({
52
56
  getLabel: () => 'Link',
53
57
  },
54
58
 
55
- editableFields: [
56
- urlField({ name: 'href', label: 'Link URL', required: true }),
57
- ],
59
+ editableFields: [urlField({ name: 'href', label: 'Link URL', required: true })],
58
60
 
59
61
  clientRenderer: (node, context) => {
60
62
  const children = context.buildChildren(
61
63
  node.children as any,
62
64
  context.elementPath,
63
65
  context.parentComponentName,
64
- context.componentContext
66
+ context.componentContext,
65
67
  );
66
68
  return h('div', { key: context.key }, children);
67
69
  },
@@ -25,67 +25,67 @@ const CMSSortConfigSchema = z.union([
25
25
  field: z.string(),
26
26
  order: z.enum(['asc', 'desc']).optional(),
27
27
  }),
28
- z.array(z.object({
29
- field: z.string(),
30
- order: z.enum(['asc', 'desc']).optional(),
31
- })),
28
+ z.array(
29
+ z.object({
30
+ field: z.string(),
31
+ order: z.enum(['asc', 'desc']).optional(),
32
+ }),
33
+ ),
32
34
  ]);
33
35
 
34
36
  // Schema is the SINGLE source of truth
35
- const ListNodeSchemaInternal = z.object({
36
- type: z.literal('list'),
37
- /**
38
- * Data source type:
39
- * - 'prop': Read items from component props (default)
40
- * - 'collection': Query items from CMS collection
41
- */
42
- sourceType: z.enum(['prop', 'collection']).default('prop'),
43
- /**
44
- * Source identifier:
45
- * - For sourceType 'prop': Prop name (e.g., "items") or template expression (e.g., "{{category.items}}")
46
- * - For sourceType 'collection': Collection name (e.g., "posts", "authors")
47
- */
48
- source: z.string(),
49
- label: z.string().optional(), // Custom label displayed in structure tree
50
- if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
51
- /**
52
- * Variable name for item in templates.
53
- * - For sourceType 'prop': defaults to 'item'
54
- * - For sourceType 'collection': defaults to singularized collection name
55
- */
56
- itemAs: z.string().optional(),
57
-
58
- // Collection-only options (ignored when sourceType: 'prop')
59
- /** Direct item IDs or template expression for referenced items (e.g., "{{post.authorId}}") */
60
- items: z.union([z.string(), z.array(z.string())]).optional(),
61
- /** Filter conditions */
62
- filter: z.union([
63
- CMSFilterConditionSchema,
64
- z.array(CMSFilterConditionSchema),
65
- z.record(z.unknown()),
66
- ]).optional(),
67
- /** Sort configuration */
68
- sort: CMSSortConfigSchema.optional(),
69
- /** Exclude the current CMS item from the list (useful for "related items" sections) */
70
- excludeCurrentItem: z.boolean().optional(),
71
- /**
72
- * Emit item template for dynamic client-side rendering.
73
- * When true, SSR emits a `<template data-meno-item>` element with unprocessed
74
- * {{item.field}} placeholders. MenoFilter uses this to render items beyond
75
- * the SSR'd limit dynamically.
76
- */
77
- emitTemplate: z.boolean().optional(),
78
-
79
- // Shared options
80
- /** Maximum number of items to return */
81
- limit: z.number().optional(),
82
- /** Number of items to skip */
83
- offset: z.number().optional(),
84
- /** Children are repeated for each item */
85
- children: z.array(z.unknown()).optional(),
86
- /** @deprecated Legacy property - use source + sourceType instead */
87
- collection: z.union([z.string(), z.array(z.any())]).optional(),
88
- }).passthrough();
37
+ const ListNodeSchemaInternal = z
38
+ .object({
39
+ type: z.literal('list'),
40
+ /**
41
+ * Data source type:
42
+ * - 'prop': Read items from component props (default)
43
+ * - 'collection': Query items from CMS collection
44
+ */
45
+ sourceType: z.enum(['prop', 'collection']).default('prop'),
46
+ /**
47
+ * Source identifier:
48
+ * - For sourceType 'prop': Prop name (e.g., "items") or template expression (e.g., "{{category.items}}")
49
+ * - For sourceType 'collection': Collection name (e.g., "posts", "authors")
50
+ */
51
+ source: z.string(),
52
+ label: z.string().optional(), // Custom label displayed in structure tree
53
+ if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
54
+ /**
55
+ * Variable name for item in templates.
56
+ * - For sourceType 'prop': defaults to 'item'
57
+ * - For sourceType 'collection': defaults to singularized collection name
58
+ */
59
+ itemAs: z.string().optional(),
60
+
61
+ // Collection-only options (ignored when sourceType: 'prop')
62
+ /** Direct item IDs or template expression for referenced items (e.g., "{{post.authorId}}") */
63
+ items: z.union([z.string(), z.array(z.string())]).optional(),
64
+ /** Filter conditions */
65
+ filter: z.union([CMSFilterConditionSchema, z.array(CMSFilterConditionSchema), z.record(z.unknown())]).optional(),
66
+ /** Sort configuration */
67
+ sort: CMSSortConfigSchema.optional(),
68
+ /** Exclude the current CMS item from the list (useful for "related items" sections) */
69
+ excludeCurrentItem: z.boolean().optional(),
70
+ /**
71
+ * Emit item template for dynamic client-side rendering.
72
+ * When true, SSR emits a `<template data-meno-item>` element with unprocessed
73
+ * {{item.field}} placeholders. MenoFilter uses this to render items beyond
74
+ * the SSR'd limit dynamically.
75
+ */
76
+ emitTemplate: z.boolean().optional(),
77
+
78
+ // Shared options
79
+ /** Maximum number of items to return */
80
+ limit: z.number().optional(),
81
+ /** Number of items to skip */
82
+ offset: z.number().optional(),
83
+ /** Children are repeated for each item */
84
+ children: z.array(z.unknown()).optional(),
85
+ /** @deprecated Legacy property - use source + sourceType instead */
86
+ collection: z.union([z.string(), z.array(z.any())]).optional(),
87
+ })
88
+ .passthrough();
89
89
 
90
90
  // TypeScript type inferred from schema
91
91
  export type ListNode = z.infer<typeof ListNodeSchemaInternal>;
@@ -126,20 +126,24 @@ export const ListNodeType = createNodeType({
126
126
  const textColor = isCollection ? '#8b5cf6' : '#3b82f6';
127
127
  const label = isCollection ? 'CMS List' : 'List';
128
128
 
129
- return h('div', {
130
- key: context.key,
131
- 'data-list': 'true',
132
- 'data-source-type': sourceType,
133
- 'data-source': listNode.source,
134
- style: {
135
- padding: '8px 12px',
136
- background: bgColor,
137
- border: `1px dashed ${borderColor}`,
138
- borderRadius: '4px',
139
- color: textColor,
140
- fontSize: '12px',
129
+ return h(
130
+ 'div',
131
+ {
132
+ key: context.key,
133
+ 'data-list': 'true',
134
+ 'data-source-type': sourceType,
135
+ 'data-source': listNode.source,
136
+ style: {
137
+ padding: '8px 12px',
138
+ background: bgColor,
139
+ border: `1px dashed ${borderColor}`,
140
+ borderRadius: '4px',
141
+ color: textColor,
142
+ fontSize: '12px',
143
+ },
141
144
  },
142
- }, `[${label}: ${listNode.source || 'No source'}]`);
145
+ `[${label}: ${listNode.source || 'No source'}]`,
146
+ );
143
147
  },
144
148
 
145
149
  ssrRenderer: (_node, _context) => {
@@ -165,14 +169,14 @@ export const ListNodeType = createNodeType({
165
169
  label: 'Source',
166
170
  type: 'string',
167
171
  required: true,
168
- placeholder: 'e.g., items or posts'
172
+ placeholder: 'e.g., items or posts',
169
173
  },
170
174
  {
171
175
  name: 'itemAs',
172
176
  label: 'Item Variable',
173
177
  type: 'string',
174
178
  required: false,
175
- placeholder: 'default: item (prop) or singular (collection)'
176
- }
179
+ placeholder: 'default: item (prop) or singular (collection)',
180
+ },
177
181
  ],
178
182
  });
@@ -9,23 +9,25 @@ import { StyleValueSchema, InteractiveStylesSchema, IfConditionSchema } from '..
9
9
  import { createNodeType } from '../createNodeType';
10
10
 
11
11
  // Schema is the SINGLE source of truth
12
- const LocaleListNodeSchemaInternal = z.object({
13
- type: z.literal('locale-list'),
14
- label: z.string().optional(), // Custom label displayed in structure tree
15
- if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
16
- style: StyleValueSchema.optional(),
17
- itemStyle: StyleValueSchema.optional(),
18
- activeItemStyle: StyleValueSchema.optional(),
19
- separatorStyle: StyleValueSchema.optional(),
20
- showCurrent: z.boolean().optional(),
21
- showSeparator: z.boolean().optional(),
22
- showFlag: z.boolean().optional(),
23
- flagStyle: StyleValueSchema.optional(),
24
- interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
25
- generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
26
- displayType: z.enum(['code', 'name', 'nativeName']).optional(), // How to display locale text
27
- attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
28
- }).passthrough();
12
+ const LocaleListNodeSchemaInternal = z
13
+ .object({
14
+ type: z.literal('locale-list'),
15
+ label: z.string().optional(), // Custom label displayed in structure tree
16
+ if: IfConditionSchema.optional(), // Conditional rendering - skip node when false
17
+ style: StyleValueSchema.optional(),
18
+ itemStyle: StyleValueSchema.optional(),
19
+ activeItemStyle: StyleValueSchema.optional(),
20
+ separatorStyle: StyleValueSchema.optional(),
21
+ showCurrent: z.boolean().optional(),
22
+ showSeparator: z.boolean().optional(),
23
+ showFlag: z.boolean().optional(),
24
+ flagStyle: StyleValueSchema.optional(),
25
+ interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)
26
+ generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)
27
+ displayType: z.enum(['code', 'name', 'nativeName']).optional(), // How to display locale text
28
+ attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
29
+ })
30
+ .passthrough();
29
31
 
30
32
  // TypeScript type inferred from schema
31
33
  export type LocaleListNode = z.infer<typeof LocaleListNodeSchemaInternal>;
@@ -54,10 +56,14 @@ export const LocaleListNodeType = createNodeType({
54
56
 
55
57
  clientRenderer: (_node, context) => {
56
58
  // In editor, shows placeholder
57
- return h('div', {
58
- key: context.key,
59
- 'data-locale-list': 'true',
60
- }, '[Locale List]');
59
+ return h(
60
+ 'div',
61
+ {
62
+ key: context.key,
63
+ 'data-locale-list': 'true',
64
+ },
65
+ '[Locale List]',
66
+ );
61
67
  },
62
68
 
63
69
  ssrRenderer: (_node, _context) => {
@@ -9,13 +9,12 @@ import { createNodeType } from '../createNodeType';
9
9
  // Schema is the SINGLE source of truth
10
10
  // Note: default uses z.any() to avoid circular reference with ComponentNodeSchema
11
11
  // Full validation is done via the schema in validation/schemas.ts
12
- const SlotMarkerSchemaInternal = z.object({
13
- type: z.literal('slot'),
14
- default: z.union([
15
- z.array(z.any()),
16
- z.string(),
17
- ]).optional(),
18
- }).passthrough();
12
+ const SlotMarkerSchemaInternal = z
13
+ .object({
14
+ type: z.literal('slot'),
15
+ default: z.union([z.array(z.any()), z.string()]).optional(),
16
+ })
17
+ .passthrough();
19
18
 
20
19
  // TypeScript type inferred from schema
21
20
  export type SlotMarker = z.infer<typeof SlotMarkerSchemaInternal>;
@@ -11,7 +11,11 @@ import type { NodeTypeDefinition } from '../NodeTypeDefinition';
11
11
 
12
12
  // Import all node type definitions (each file exports type, schema, and definition)
13
13
  import { HtmlNodeType, HtmlNodeSchema, type HtmlNode } from './HtmlNodeType';
14
- import { ComponentInstanceNodeType, ComponentInstanceNodeSchema, type ComponentInstanceNode } from './ComponentInstanceNodeType';
14
+ import {
15
+ ComponentInstanceNodeType,
16
+ ComponentInstanceNodeSchema,
17
+ type ComponentInstanceNode,
18
+ } from './ComponentInstanceNodeType';
15
19
  import { SlotMarkerType, SlotMarkerSchema, type SlotMarker } from './SlotMarkerType';
16
20
  import { EmbedNodeType, EmbedNodeSchema, type EmbedNode } from './EmbedNodeType';
17
21
  import { LinkNodeType, LinkNodeSchema, type LinkNode } from './LinkNodeType';
@@ -55,7 +59,11 @@ export function registerBuiltInNodeTypes(): void {
55
59
 
56
60
  // Re-export individual node types for direct access
57
61
  export { HtmlNodeType, HtmlNodeSchema, type HtmlNode } from './HtmlNodeType';
58
- export { ComponentInstanceNodeType, ComponentInstanceNodeSchema, type ComponentInstanceNode } from './ComponentInstanceNodeType';
62
+ export {
63
+ ComponentInstanceNodeType,
64
+ ComponentInstanceNodeSchema,
65
+ type ComponentInstanceNode,
66
+ } from './ComponentInstanceNodeType';
59
67
  export { SlotMarkerType, SlotMarkerSchema, type SlotMarker } from './SlotMarkerType';
60
68
  export { EmbedNodeType, EmbedNodeSchema, type EmbedNode } from './EmbedNodeType';
61
69
  export { LinkNodeType, LinkNodeSchema, type LinkNode } from './LinkNodeType';
@@ -95,7 +95,7 @@ describe('responsiveScaling', () => {
95
95
  const scales: ResponsiveScales = {
96
96
  enabled: true,
97
97
  baseReference: 16,
98
- fontSize: { tablet: 0.88 }
98
+ fontSize: { tablet: 0.88 },
99
99
  };
100
100
  const scale = getScaleMultiplier(scales, 'fontSize', 'mobile');
101
101
  expect(scale).toBeNull();
@@ -105,7 +105,7 @@ describe('responsiveScaling', () => {
105
105
  const scales: ResponsiveScales = {
106
106
  enabled: true,
107
107
  baseReference: 16,
108
- fontSize: { large: 0.95, tablet: 0.88, small: 0.82, mobile: 0.75 }
108
+ fontSize: { large: 0.95, tablet: 0.88, small: 0.82, mobile: 0.75 },
109
109
  };
110
110
  expect(getScaleMultiplier(scales, 'fontSize', 'large')).toBe(0.95);
111
111
  expect(getScaleMultiplier(scales, 'fontSize', 'small')).toBe(0.82);
@@ -115,7 +115,7 @@ describe('responsiveScaling', () => {
115
115
  const scales: ResponsiveScales = {
116
116
  enabled: true,
117
117
  baseReference: 16,
118
- fontSize: { tablet: 0.88, mobile: 0.75 }
118
+ fontSize: { tablet: 0.88, mobile: 0.75 },
119
119
  };
120
120
  expect(getScaleMultiplier(scales, 'fontSize', 'large')).toBeNull();
121
121
  expect(getScaleMultiplier(scales, 'fontSize', 'small')).toBeNull();
@@ -277,7 +277,7 @@ describe('responsiveScaling', () => {
277
277
  const scales: ResponsiveScales = {
278
278
  enabled: true,
279
279
  baseReference: 16,
280
- fontSize: { tablet: 0.88 }
280
+ fontSize: { tablet: 0.88 },
281
281
  };
282
282
  const result = getResponsiveValues('20px', 'fontSize', scales);
283
283
  expect(result.base).toBe('20px');
@@ -289,18 +289,13 @@ describe('responsiveScaling', () => {
289
289
  const scales: ResponsiveScales = {
290
290
  enabled: true,
291
291
  baseReference: 16,
292
- fontSize: { large: 0.95, tablet: 0.88, small: 0.82, mobile: 0.75 }
292
+ fontSize: { large: 0.95, tablet: 0.88, small: 0.82, mobile: 0.75 },
293
293
  };
294
- const result = getResponsiveValues(
295
- '67px',
296
- 'fontSize',
297
- scales,
298
- ['large', 'tablet', 'small', 'mobile']
299
- );
294
+ const result = getResponsiveValues('67px', 'fontSize', scales, ['large', 'tablet', 'small', 'mobile']);
300
295
  expect(result.base).toBe('67px');
301
- expect(result.large).toBe('64px'); // 67 + (67-16) * (0.95-1) = 67 - 2.55 ≈ 64
296
+ expect(result.large).toBe('64px'); // 67 + (67-16) * (0.95-1) = 67 - 2.55 ≈ 64
302
297
  expect(result.tablet).toBe('61px'); // 0.88 scale
303
- expect(result.small).toBe('58px'); // 67 + (67-16) * (0.82-1) = 67 - 9.18 ≈ 58
298
+ expect(result.small).toBe('58px'); // 67 + (67-16) * (0.82-1) = 67 - 9.18 ≈ 58
304
299
  expect(result.mobile).toBe('54px'); // 0.75 scale
305
300
  });
306
301
 
@@ -308,15 +303,10 @@ describe('responsiveScaling', () => {
308
303
  const scales: ResponsiveScales = {
309
304
  enabled: true,
310
305
  baseReference: 16,
311
- fontSize: { large: 0.95, tablet: 0.88, small: 0.82, mobile: 0.75 }
306
+ fontSize: { large: 0.95, tablet: 0.88, small: 0.82, mobile: 0.75 },
312
307
  };
313
308
  // Only request large and small breakpoints
314
- const result = getResponsiveValues(
315
- '67px',
316
- 'fontSize',
317
- scales,
318
- ['large', 'small']
319
- );
309
+ const result = getResponsiveValues('67px', 'fontSize', scales, ['large', 'small']);
320
310
  expect(result.base).toBe('67px');
321
311
  expect(result.large).toBe('64px');
322
312
  expect(result.small).toBe('58px');
@@ -328,19 +318,14 @@ describe('responsiveScaling', () => {
328
318
  const scales: ResponsiveScales = {
329
319
  enabled: true,
330
320
  baseReference: 16,
331
- fontSize: { tablet: 0.88, mobile: 0.75 }
321
+ fontSize: { tablet: 0.88, mobile: 0.75 },
332
322
  };
333
323
  // Request breakpoints that don't have scales configured
334
- const result = getResponsiveValues(
335
- '67px',
336
- 'fontSize',
337
- scales,
338
- ['large', 'tablet', 'small', 'mobile']
339
- );
324
+ const result = getResponsiveValues('67px', 'fontSize', scales, ['large', 'tablet', 'small', 'mobile']);
340
325
  expect(result.base).toBe('67px');
341
- expect(result.large).toBeUndefined(); // No scale configured
326
+ expect(result.large).toBeUndefined(); // No scale configured
342
327
  expect(result.tablet).toBe('61px');
343
- expect(result.small).toBeUndefined(); // No scale configured
328
+ expect(result.small).toBeUndefined(); // No scale configured
344
329
  expect(result.mobile).toBe('54px');
345
330
  });
346
331
 
@@ -501,8 +486,7 @@ describe('responsiveScaling', () => {
501
486
  });
502
487
 
503
488
  test('returns plain px when min === max', () => {
504
- expect(buildSiteMarginClamp({ min: 16, max: 16 }, { min: 320, max: 1440 }))
505
- .toBe('16px');
489
+ expect(buildSiteMarginClamp({ min: 16, max: 16 }, { min: 320, max: 1440 })).toBe('16px');
506
490
  });
507
491
 
508
492
  test('default DEFAULT_SITE_MARGIN is 16/32', () => {