meno-core 1.0.53 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (415) hide show
  1. package/.claude/settings.local.json +1 -3
  2. package/bin/cli.ts +66 -261
  3. package/build-astro.ts +150 -128
  4. package/dist/bin/cli.js +42 -185
  5. package/dist/bin/cli.js.map +2 -2
  6. package/dist/chunks/chunk-2AR55GYH.js +42 -0
  7. package/dist/chunks/chunk-2AR55GYH.js.map +7 -0
  8. package/dist/chunks/{chunk-JGWFTO6P.js → chunk-2IIQK7T3.js} +2624 -1389
  9. package/dist/chunks/chunk-2IIQK7T3.js.map +7 -0
  10. package/dist/chunks/chunk-4ZRU52J2.js +169 -0
  11. package/dist/chunks/chunk-4ZRU52J2.js.map +7 -0
  12. package/dist/chunks/{chunk-UB44F4Z2.js → chunk-5X4HCN7J.js} +5 -7
  13. package/dist/chunks/chunk-5X4HCN7J.js.map +7 -0
  14. package/dist/chunks/{chunk-WQFG7PAH.js → chunk-7CCVOL5M.js} +15 -19
  15. package/dist/chunks/chunk-7CCVOL5M.js.map +7 -0
  16. package/dist/chunks/{chunk-YBLHKYFF.js → chunk-AR7LHIFY.js} +8 -2
  17. package/dist/chunks/chunk-AR7LHIFY.js.map +7 -0
  18. package/dist/chunks/{chunk-O3NAGJP4.js → chunk-NUP7H7D3.js} +135 -41
  19. package/dist/chunks/chunk-NUP7H7D3.js.map +7 -0
  20. package/dist/chunks/{chunk-X754AHS5.js → chunk-QWTQZHG3.js} +194 -90
  21. package/dist/chunks/chunk-QWTQZHG3.js.map +7 -0
  22. package/dist/chunks/{chunk-H3GJ4H2U.js → chunk-XTKNX4FW.js} +216 -87
  23. package/dist/chunks/chunk-XTKNX4FW.js.map +7 -0
  24. package/dist/chunks/{fs-JGINUXGL.js → fs-G3ANWEFP.js} +2 -2
  25. package/dist/lib/client/index.js +1003 -475
  26. package/dist/lib/client/index.js.map +3 -3
  27. package/dist/lib/server/index.js +14393 -6371
  28. package/dist/lib/server/index.js.map +4 -4
  29. package/dist/lib/shared/index.js +342 -101
  30. package/dist/lib/shared/index.js.map +4 -4
  31. package/dist/lib/shared/richtext/index.js +1 -1
  32. package/dist/lib/test-utils/index.js +64 -80
  33. package/dist/lib/test-utils/index.js.map +2 -2
  34. package/entries/client-router.tsx +10 -8
  35. package/lib/client/ClientInitializer.ts +8 -8
  36. package/lib/client/ErrorBoundary.test.tsx +246 -186
  37. package/lib/client/ErrorBoundary.tsx +183 -132
  38. package/lib/client/componentRegistry.test.ts +96 -108
  39. package/lib/client/componentRegistry.ts +1 -3
  40. package/lib/client/contexts/ThemeContext.tsx +3 -2
  41. package/lib/client/core/ComponentBuilder.test.ts +663 -560
  42. package/lib/client/core/ComponentBuilder.ts +427 -155
  43. package/lib/client/core/ComponentRenderer.test.tsx +2 -4
  44. package/lib/client/core/ComponentRenderer.tsx +46 -33
  45. package/lib/client/core/builders/embedBuilder.ts +242 -54
  46. package/lib/client/core/builders/linkBuilder.ts +72 -45
  47. package/lib/client/core/builders/linkNodeBuilder.ts +79 -54
  48. package/lib/client/core/builders/listBuilder.ts +155 -89
  49. package/lib/client/core/builders/localeListBuilder.ts +97 -62
  50. package/lib/client/core/builders/types.ts +5 -5
  51. package/lib/client/core/cmsTemplateProcessor.ts +8 -9
  52. package/lib/client/elementRegistry.ts +3 -3
  53. package/lib/client/fontFamiliesService.test.ts +2 -10
  54. package/lib/client/fontFamiliesService.ts +3 -3
  55. package/lib/client/hmr/HMRManager.tsx +47 -30
  56. package/lib/client/hmrCssReload.ts +49 -14
  57. package/lib/client/hmrWebSocket.ts +14 -19
  58. package/lib/client/hooks/useColorVariables.test.ts +21 -21
  59. package/lib/client/hooks/useColorVariables.ts +23 -18
  60. package/lib/client/hooks/usePropertyAutocomplete.ts +4 -6
  61. package/lib/client/hooks/useVariables.ts +6 -4
  62. package/lib/client/hydration/HydrationUtils.test.ts +24 -25
  63. package/lib/client/hydration/HydrationUtils.ts +3 -4
  64. package/lib/client/i18nConfigService.test.ts +2 -7
  65. package/lib/client/i18nConfigService.ts +2 -2
  66. package/lib/client/meno-filter/MenoFilter.test.ts +47 -49
  67. package/lib/client/meno-filter/MenoFilter.ts +14 -15
  68. package/lib/client/meno-filter/bindings.ts +18 -43
  69. package/lib/client/meno-filter/init.ts +4 -4
  70. package/lib/client/meno-filter/renderer.ts +30 -32
  71. package/lib/client/meno-filter/script.generated.ts +1 -3
  72. package/lib/client/meno-filter/ui.ts +4 -6
  73. package/lib/client/meno-filter/updates.ts +18 -23
  74. package/lib/client/meno-filter/utils.ts +1 -1
  75. package/lib/client/navigation.test.ts +174 -178
  76. package/lib/client/navigation.ts +0 -1
  77. package/lib/client/responsiveStyleResolver.knownTokens.test.ts +71 -0
  78. package/lib/client/responsiveStyleResolver.test.ts +234 -232
  79. package/lib/client/responsiveStyleResolver.ts +74 -20
  80. package/lib/client/routing/RouteLoader.test.ts +24 -25
  81. package/lib/client/routing/RouteLoader.ts +27 -35
  82. package/lib/client/routing/Router.tsx +210 -153
  83. package/lib/client/scripts/ScriptExecutor.test.ts +157 -158
  84. package/lib/client/scripts/ScriptExecutor.ts +18 -36
  85. package/lib/client/services/PrefetchService.test.ts +3 -3
  86. package/lib/client/services/PrefetchService.ts +23 -29
  87. package/lib/client/styleProcessor.test.ts +9 -9
  88. package/lib/client/styleProcessor.ts +24 -15
  89. package/lib/client/styles/StyleInjector.test.ts +122 -115
  90. package/lib/client/styles/StyleInjector.ts +10 -7
  91. package/lib/client/styles/UtilityClassCollector.ts +62 -28
  92. package/lib/client/styles/cspNonce.test.ts +2 -5
  93. package/lib/client/templateEngine.test.ts +554 -488
  94. package/lib/client/templateEngine.ts +203 -73
  95. package/lib/client/theme.test.ts +1 -1
  96. package/lib/client/theme.ts +0 -1
  97. package/lib/client/utils/toast.ts +0 -1
  98. package/lib/server/__integration__/api-routes.test.ts +8 -4
  99. package/lib/server/__integration__/cms-integration.test.ts +1 -4
  100. package/lib/server/__integration__/server-lifecycle.test.ts +4 -5
  101. package/lib/server/__integration__/ssr-rendering.test.ts +47 -37
  102. package/lib/server/__integration__/static-assets.test.ts +3 -3
  103. package/lib/server/__integration__/test-helpers.ts +87 -74
  104. package/lib/server/ab/generateFunctions.ts +12 -10
  105. package/lib/server/astro/cmsPageEmitter.ts +26 -42
  106. package/lib/server/astro/componentEmitter.ts +35 -43
  107. package/lib/server/astro/cssCollector.ts +10 -26
  108. package/lib/server/astro/nodeToAstro.test.ts +1754 -34
  109. package/lib/server/astro/nodeToAstro.ts +232 -216
  110. package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +115 -119
  111. package/lib/server/astro/normalizeOrphanTemplateProps.ts +11 -18
  112. package/lib/server/astro/pageEmitter.ts +9 -13
  113. package/lib/server/astro/tailwindMapper.test.ts +10 -37
  114. package/lib/server/astro/tailwindMapper.ts +33 -40
  115. package/lib/server/astro/templateTransformer.ts +17 -20
  116. package/lib/server/createServer.ts +7 -19
  117. package/lib/server/cssGenerator.test.ts +35 -44
  118. package/lib/server/cssGenerator.ts +8 -19
  119. package/lib/server/fileWatcher.test.ts +164 -13
  120. package/lib/server/fileWatcher.ts +209 -124
  121. package/lib/server/index.ts +14 -17
  122. package/lib/server/jsonLoader.test.ts +39 -2
  123. package/lib/server/jsonLoader.ts +39 -34
  124. package/lib/server/middleware/cors.test.ts +21 -21
  125. package/lib/server/middleware/cors.ts +28 -4
  126. package/lib/server/middleware/errorHandler.test.ts +7 -5
  127. package/lib/server/middleware/errorHandler.ts +3 -8
  128. package/lib/server/middleware/index.ts +0 -1
  129. package/lib/server/middleware/logger.test.ts +10 -8
  130. package/lib/server/middleware/logger.ts +17 -29
  131. package/lib/server/migrateTemplates.ts +3 -3
  132. package/lib/server/pageCache.test.ts +76 -77
  133. package/lib/server/pageCache.ts +0 -1
  134. package/lib/server/projectContext.ts +5 -4
  135. package/lib/server/providers/fileSystemCMSProvider.test.ts +142 -99
  136. package/lib/server/providers/fileSystemCMSProvider.ts +62 -38
  137. package/lib/server/routes/api/cms.test.ts +26 -14
  138. package/lib/server/routes/api/cms.ts +9 -14
  139. package/lib/server/routes/api/colors.test.ts +2 -2
  140. package/lib/server/routes/api/components.ts +31 -35
  141. package/lib/server/routes/api/config.ts +3 -4
  142. package/lib/server/routes/api/core-routes.ts +49 -76
  143. package/lib/server/routes/api/enums.test.ts +2 -2
  144. package/lib/server/routes/api/functions.ts +9 -17
  145. package/lib/server/routes/api/index.ts +3 -6
  146. package/lib/server/routes/api/pages.ts +8 -11
  147. package/lib/server/routes/api/shared.test.ts +1 -1
  148. package/lib/server/routes/api/shared.ts +12 -9
  149. package/lib/server/routes/api/variables.test.ts +3 -5
  150. package/lib/server/routes/api/variables.ts +1 -1
  151. package/lib/server/routes/index.ts +25 -28
  152. package/lib/server/routes/pages.ts +35 -31
  153. package/lib/server/routes/static.ts +17 -6
  154. package/lib/server/runtime/bundler.ts +98 -61
  155. package/lib/server/runtime/fs.ts +16 -26
  156. package/lib/server/runtime/httpServer.ts +8 -12
  157. package/lib/server/services/ColorService.test.ts +3 -3
  158. package/lib/server/services/ColorService.ts +37 -29
  159. package/lib/server/services/EnumService.test.ts +4 -8
  160. package/lib/server/services/EnumService.ts +11 -3
  161. package/lib/server/services/VariableService.test.ts +8 -12
  162. package/lib/server/services/VariableService.ts +11 -3
  163. package/lib/server/services/cmsService.test.ts +158 -120
  164. package/lib/server/services/cmsService.ts +36 -146
  165. package/lib/server/services/componentService.test.ts +125 -45
  166. package/lib/server/services/componentService.ts +70 -46
  167. package/lib/server/services/configService.test.ts +22 -45
  168. package/lib/server/services/configService.ts +50 -27
  169. package/lib/server/services/fileWatcherService.ts +42 -8
  170. package/lib/server/services/index.ts +0 -1
  171. package/lib/server/services/pageService.test.ts +8 -10
  172. package/lib/server/services/pageService.ts +32 -18
  173. package/lib/server/ssr/attributeBuilder.ts +18 -8
  174. package/lib/server/ssr/buildErrorOverlay.ts +11 -12
  175. package/lib/server/ssr/clientDataInjector.ts +7 -21
  176. package/lib/server/ssr/cmsSSRProcessor.ts +4 -8
  177. package/lib/server/ssr/cssCollector.ts +1 -1
  178. package/lib/server/ssr/errorOverlay.test.ts +1 -1
  179. package/lib/server/ssr/errorOverlay.ts +3 -9
  180. package/lib/server/ssr/htmlGenerator.nonce.test.ts +9 -14
  181. package/lib/server/ssr/htmlGenerator.test.ts +120 -44
  182. package/lib/server/ssr/htmlGenerator.ts +126 -91
  183. package/lib/server/ssr/imageMetadata.test.ts +3 -1
  184. package/lib/server/ssr/imageMetadata.ts +27 -21
  185. package/lib/server/ssr/jsCollector.test.ts +8 -18
  186. package/lib/server/ssr/jsCollector.ts +3 -8
  187. package/lib/server/ssr/liveReloadIntegration.test.ts +76 -36
  188. package/lib/server/ssr/metaTagGenerator.ts +2 -2
  189. package/lib/server/ssr/ssrRenderer.branches.test.ts +1103 -0
  190. package/lib/server/ssr/ssrRenderer.test.ts +316 -256
  191. package/lib/server/ssr/ssrRenderer.ts +795 -243
  192. package/lib/server/ssrRenderer.test.ts +1048 -954
  193. package/lib/server/utils/jsonLineMapper.test.ts +28 -28
  194. package/lib/server/utils/jsonLineMapper.ts +7 -7
  195. package/lib/server/validateStyleCoverage.ts +18 -21
  196. package/lib/server/websocketManager.ts +28 -19
  197. package/lib/shared/attributeNodeUtils.test.ts +15 -15
  198. package/lib/shared/attributeNodeUtils.ts +5 -12
  199. package/lib/shared/breakpoints.test.ts +5 -5
  200. package/lib/shared/breakpoints.ts +4 -11
  201. package/lib/shared/cmsQuery.test.ts +81 -0
  202. package/lib/shared/cmsQuery.ts +92 -0
  203. package/lib/shared/cmsQueryParser.test.ts +50 -42
  204. package/lib/shared/cmsQueryParser.ts +60 -38
  205. package/lib/shared/colorConversions.ts +9 -9
  206. package/lib/shared/colorVariableUtils.test.ts +27 -5
  207. package/lib/shared/colorVariableUtils.ts +21 -12
  208. package/lib/shared/componentRefs.ts +1 -5
  209. package/lib/shared/constants.test.ts +3 -3
  210. package/lib/shared/constants.ts +8 -8
  211. package/lib/shared/cssGeneration.test.ts +285 -144
  212. package/lib/shared/cssGeneration.ts +217 -531
  213. package/lib/shared/cssNamedColors.ts +152 -30
  214. package/lib/shared/cssProperties.test.ts +69 -70
  215. package/lib/shared/cssProperties.ts +298 -114
  216. package/lib/shared/elementClassName.test.ts +109 -109
  217. package/lib/shared/elementClassName.ts +3 -3
  218. package/lib/shared/elementUtils.ts +12 -16
  219. package/lib/shared/errorLogger.test.ts +12 -12
  220. package/lib/shared/errorLogger.ts +2 -10
  221. package/lib/shared/errors.test.ts +2 -13
  222. package/lib/shared/errors.ts +2 -8
  223. package/lib/shared/expressionEvaluator.test.ts +145 -0
  224. package/lib/shared/expressionEvaluator.ts +52 -24
  225. package/lib/shared/fontLoader.test.ts +32 -18
  226. package/lib/shared/fontLoader.ts +2 -2
  227. package/lib/shared/friendlyError.ts +2 -3
  228. package/lib/shared/gradientUtils.test.ts +3 -7
  229. package/lib/shared/gradientUtils.ts +17 -14
  230. package/lib/shared/hrefRefs.test.ts +2 -2
  231. package/lib/shared/hrefRefs.ts +2 -10
  232. package/lib/shared/i18n.test.ts +4 -4
  233. package/lib/shared/i18n.ts +18 -38
  234. package/lib/shared/index.ts +27 -0
  235. package/lib/shared/inlineSvgStyleRules.ts +14 -13
  236. package/lib/shared/interactiveStyleMappings.test.ts +32 -54
  237. package/lib/shared/interactiveStyleMappings.ts +11 -24
  238. package/lib/shared/interactiveStyles.test.ts +165 -188
  239. package/lib/shared/interfaces/contentProvider.ts +1 -1
  240. package/lib/shared/itemTemplateUtils.test.ts +11 -17
  241. package/lib/shared/itemTemplateUtils.ts +27 -39
  242. package/lib/shared/jsonRepair.ts +16 -10
  243. package/lib/shared/libraryLoader.test.ts +21 -55
  244. package/lib/shared/libraryLoader.ts +7 -22
  245. package/lib/shared/linkUtils.ts +1 -1
  246. package/lib/shared/logger.test.ts +66 -0
  247. package/lib/shared/logger.ts +94 -0
  248. package/lib/shared/markdown.ts +25 -0
  249. package/lib/shared/netlifyLocale404.test.ts +179 -0
  250. package/lib/shared/netlifyLocale404.ts +110 -0
  251. package/lib/shared/nodeUtils.test.ts +28 -16
  252. package/lib/shared/nodeUtils.ts +76 -23
  253. package/lib/shared/pathArrayUtils.test.ts +1 -2
  254. package/lib/shared/pathArrayUtils.ts +1 -1
  255. package/lib/shared/pathSecurity.ts +2 -2
  256. package/lib/shared/pathUtils.test.ts +4 -6
  257. package/lib/shared/pathUtils.ts +42 -49
  258. package/lib/shared/paths/Path.test.ts +2 -2
  259. package/lib/shared/paths/Path.ts +0 -1
  260. package/lib/shared/paths/PathConverter.test.ts +1 -1
  261. package/lib/shared/paths/PathConverter.ts +17 -20
  262. package/lib/shared/paths/PathUtils.ts +13 -13
  263. package/lib/shared/paths/PathValidator.test.ts +2 -15
  264. package/lib/shared/paths/PathValidator.ts +12 -10
  265. package/lib/shared/paths/index.ts +1 -2
  266. package/lib/shared/permissions.test.ts +168 -0
  267. package/lib/shared/permissions.ts +162 -0
  268. package/lib/shared/propResolver.test.ts +240 -244
  269. package/lib/shared/propResolver.ts +15 -26
  270. package/lib/shared/pxToRem.test.ts +7 -6
  271. package/lib/shared/pxToRem.ts +2 -5
  272. package/lib/shared/registry/BaseNodeTypeRegistry.test.ts +12 -6
  273. package/lib/shared/registry/ClientRegistry.ts +0 -2
  274. package/lib/shared/registry/ComponentRegistry.test.ts +46 -32
  275. package/lib/shared/registry/ComponentRegistry.ts +12 -9
  276. package/lib/shared/registry/NodeTypeDefinition.ts +16 -9
  277. package/lib/shared/registry/RegistryManager.ts +1 -2
  278. package/lib/shared/registry/SSRRegistry.ts +0 -2
  279. package/lib/shared/registry/createNodeType.ts +7 -9
  280. package/lib/shared/registry/defineNodeType.ts +2 -6
  281. package/lib/shared/registry/fieldPresets.ts +3 -1
  282. package/lib/shared/registry/index.ts +0 -1
  283. package/lib/shared/registry/nodeTypes/ComponentInstanceNodeType.ts +14 -15
  284. package/lib/shared/registry/nodeTypes/CustomNodeType.ts +103 -0
  285. package/lib/shared/registry/nodeTypes/EmbedNodeType.ts +18 -11
  286. package/lib/shared/registry/nodeTypes/HtmlNodeType.ts +48 -19
  287. package/lib/shared/registry/nodeTypes/IslandNodeType.ts +129 -0
  288. package/lib/shared/registry/nodeTypes/LinkNodeType.ts +21 -19
  289. package/lib/shared/registry/nodeTypes/ListNodeType.ts +117 -77
  290. package/lib/shared/registry/nodeTypes/LocaleListNodeType.ts +27 -21
  291. package/lib/shared/registry/nodeTypes/MarkdownNodeType.ts +78 -0
  292. package/lib/shared/registry/nodeTypes/SlotMarkerType.ts +12 -8
  293. package/lib/shared/registry/nodeTypes/index.ts +26 -3
  294. package/lib/shared/responsiveScaling.test.ts +16 -34
  295. package/lib/shared/responsiveScaling.ts +61 -42
  296. package/lib/shared/responsiveStyleUtils.test.ts +0 -1
  297. package/lib/shared/responsiveStyleUtils.ts +11 -13
  298. package/lib/shared/richtext/htmlToTiptap.test.ts +139 -130
  299. package/lib/shared/richtext/htmlToTiptap.ts +2 -4
  300. package/lib/shared/richtext/tiptapToHtml.test.ts +5 -6
  301. package/lib/shared/richtext/types.ts +1 -8
  302. package/lib/shared/slugTranslator.test.ts +13 -13
  303. package/lib/shared/slugTranslator.ts +12 -16
  304. package/lib/shared/slugify.ts +9 -15
  305. package/lib/shared/styleNodeUtils.test.ts +8 -8
  306. package/lib/shared/styleNodeUtils.ts +18 -20
  307. package/lib/shared/styleUtils.test.ts +87 -61
  308. package/lib/shared/styleUtils.ts +5 -6
  309. package/lib/shared/themeDefaults.test.ts +11 -14
  310. package/lib/shared/themeDefaults.ts +3 -4
  311. package/lib/shared/tree/PathBuilder.test.ts +63 -145
  312. package/lib/shared/tree/PathBuilder.ts +59 -47
  313. package/lib/shared/treePathUtils.test.ts +51 -12
  314. package/lib/shared/treePathUtils.ts +91 -60
  315. package/lib/shared/types/api.ts +105 -8
  316. package/lib/shared/types/cms.test.ts +34 -0
  317. package/lib/shared/types/cms.ts +90 -34
  318. package/lib/shared/types/comment.ts +49 -16
  319. package/lib/shared/types/components.ts +51 -25
  320. package/lib/shared/types/errors.test.ts +1 -6
  321. package/lib/shared/types/errors.ts +3 -7
  322. package/lib/shared/types/experiments.ts +28 -28
  323. package/lib/shared/types/index.ts +25 -2
  324. package/lib/shared/types/permissions.ts +139 -0
  325. package/lib/shared/types/styles.ts +0 -1
  326. package/lib/shared/types/variables.test.ts +4 -13
  327. package/lib/shared/types/variables.ts +51 -30
  328. package/lib/shared/types.ts +1 -2
  329. package/lib/shared/utilityClassConfig.ts +751 -321
  330. package/lib/shared/utilityClassMapper.durability.test.ts +117 -0
  331. package/lib/shared/utilityClassMapper.test.ts +433 -95
  332. package/lib/shared/utilityClassMapper.ts +322 -249
  333. package/lib/shared/utilityClassNames.test.ts +38 -0
  334. package/lib/shared/utilityClassNames.ts +458 -0
  335. package/lib/shared/utils.test.ts +2 -10
  336. package/lib/shared/utils.ts +19 -10
  337. package/lib/shared/validation/cmsValidators.ts +2 -1
  338. package/lib/shared/validation/commentValidators.test.ts +53 -0
  339. package/lib/shared/validation/commentValidators.ts +12 -1
  340. package/lib/shared/validation/index.ts +1 -0
  341. package/lib/shared/validation/permissionsValidators.test.ts +49 -0
  342. package/lib/shared/validation/permissionsValidators.ts +49 -0
  343. package/lib/shared/validation/propValidator.test.ts +19 -21
  344. package/lib/shared/validation/propValidator.ts +13 -18
  345. package/lib/shared/validation/schemas.test.ts +64 -32
  346. package/lib/shared/validation/schemas.ts +616 -345
  347. package/lib/shared/validation/validators.test.ts +3 -8
  348. package/lib/shared/validation/validators.ts +89 -68
  349. package/lib/shared/viewportUnits.integration.test.ts +14 -10
  350. package/lib/shared/viewportUnits.test.ts +24 -23
  351. package/lib/shared/viewportUnits.ts +12 -5
  352. package/lib/test-utils/dom-setup.ts +1 -1
  353. package/lib/test-utils/factories/ConsoleMockFactory.ts +10 -14
  354. package/lib/test-utils/factories/DomMockFactory.ts +17 -23
  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 +6 -10
  358. package/lib/test-utils/factories/StoreMockFactory.ts +18 -29
  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 +13 -19
  365. package/lib/test-utils/mocks.ts +6 -4
  366. package/package.json +3 -5
  367. package/scripts/build-for-publish.mjs +2 -4
  368. package/scripts/build-meno-filter.ts +4 -7
  369. package/tsconfig.json +1 -0
  370. package/vite.config.ts +4 -4
  371. package/build-next.ts +0 -1361
  372. package/build-static.test.ts +0 -424
  373. package/build-static.ts +0 -1074
  374. package/dist/build-static.js +0 -36
  375. package/dist/chunks/chunk-2MHDV5BF.js +0 -251
  376. package/dist/chunks/chunk-2MHDV5BF.js.map +0 -7
  377. package/dist/chunks/chunk-AZQYF6KE.js +0 -559
  378. package/dist/chunks/chunk-AZQYF6KE.js.map +0 -7
  379. package/dist/chunks/chunk-GZHGVVW3.js +0 -322
  380. package/dist/chunks/chunk-GZHGVVW3.js.map +0 -7
  381. package/dist/chunks/chunk-H3GJ4H2U.js.map +0 -7
  382. package/dist/chunks/chunk-I7YIGZXT.js +0 -467
  383. package/dist/chunks/chunk-I7YIGZXT.js.map +0 -7
  384. package/dist/chunks/chunk-IGYR22T6.js +0 -6192
  385. package/dist/chunks/chunk-IGYR22T6.js.map +0 -7
  386. package/dist/chunks/chunk-JGP5A3Y5.js +0 -1136
  387. package/dist/chunks/chunk-JGP5A3Y5.js.map +0 -7
  388. package/dist/chunks/chunk-JGWFTO6P.js.map +0 -7
  389. package/dist/chunks/chunk-O3NAGJP4.js.map +0 -7
  390. package/dist/chunks/chunk-QB2LNO4W.js +0 -77
  391. package/dist/chunks/chunk-QB2LNO4W.js.map +0 -7
  392. package/dist/chunks/chunk-R6XHAFBF.js +0 -3821
  393. package/dist/chunks/chunk-R6XHAFBF.js.map +0 -7
  394. package/dist/chunks/chunk-UB44F4Z2.js.map +0 -7
  395. package/dist/chunks/chunk-WQFG7PAH.js.map +0 -7
  396. package/dist/chunks/chunk-X754AHS5.js.map +0 -7
  397. package/dist/chunks/chunk-YBLHKYFF.js.map +0 -7
  398. package/dist/chunks/configService-R3OGU2UD.js +0 -13
  399. package/dist/chunks/configService-R3OGU2UD.js.map +0 -7
  400. package/dist/chunks/constants-STK2YBIW.js +0 -46
  401. package/dist/chunks/constants-STK2YBIW.js.map +0 -7
  402. package/dist/chunks/fs-JGINUXGL.js.map +0 -7
  403. package/dist/entries/server-router.js +0 -67
  404. package/dist/entries/server-router.js.map +0 -7
  405. package/entries/server-router.tsx +0 -81
  406. package/lib/server/providers/fileSystemPageProvider.ts +0 -160
  407. package/lib/server/webflow/buildWebflow.ts +0 -635
  408. package/lib/server/webflow/index.ts +0 -23
  409. package/lib/server/webflow/nodeToWebflow.test.ts +0 -3170
  410. package/lib/server/webflow/nodeToWebflow.ts +0 -2435
  411. package/lib/server/webflow/styleMapper.test.ts +0 -389
  412. package/lib/server/webflow/styleMapper.ts +0 -695
  413. package/lib/server/webflow/templateWrapper.ts +0 -49
  414. package/lib/server/webflow/types.ts +0 -396
  415. /package/dist/{build-static.js.map → chunks/fs-G3ANWEFP.js.map} +0 -0
@@ -5,19 +5,38 @@
5
5
  * Security: Uses jsep for safe expression parsing instead of eval/new Function()
6
6
  */
7
7
 
8
- import type { StyleMapping, HtmlMapping, ComponentDefinition, StructuredComponentDefinition, ComponentNode, HtmlNode, ComponentInstanceNode, EmbedNode, SlotMarker, StyleObject, ResponsiveStyleObject, StyleValue, TemplateContext } from '../shared/types';
8
+ import type {
9
+ StyleMapping,
10
+ HtmlMapping,
11
+ ComponentNode,
12
+ HtmlNode,
13
+ ComponentInstanceNode,
14
+ SlotMarker,
15
+ StyleObject,
16
+ ResponsiveStyleObject,
17
+ StyleValue,
18
+ TemplateContext,
19
+ } from '../shared/types';
9
20
  import { isResponsiveStyle } from '../shared/styleUtils';
10
- import { normalizeStyle as normalizeStyleShared, mergeResponsiveStyles } from '../shared/responsiveStyleUtils';
11
- import { DEFAULT_BREAKPOINTS } from '../shared/breakpoints';
21
+ import { normalizeStyle as normalizeStyleShared } from '../shared/responsiveStyleUtils';
12
22
  import { NODE_TYPE } from '../shared/constants';
13
- import { isValidNodeType, isComponentNode, isHtmlNode, isSlotMarker, isEmbedNode, isLocaleListNode, isLinkNode, isCMSListNode, isListNode } from '../shared/nodeUtils';
23
+ import {
24
+ isValidNodeType,
25
+ isComponentNode,
26
+ isHtmlNode,
27
+ isSlotMarker,
28
+ isEmbedNode,
29
+ isLocaleListNode,
30
+ isLinkNode,
31
+ isListNode,
32
+ } from '../shared/nodeUtils';
14
33
  import { applyStylesToNode } from '../shared/styleNodeUtils';
15
34
  import { isRichTextMarker, richTextMarkerToHtml } from '../shared/propResolver';
16
- import { isTiptapDocument, tiptapToHtml } from '../shared/richtext';
17
35
  import { hasItemTemplates } from '../shared/itemTemplateUtils';
18
36
  import { safeEvaluate } from '../shared/expressionEvaluator';
19
37
  import { RAW_HTML_PREFIX } from '../shared/constants';
20
38
  import { getGlobalTemplateContext } from '../shared/globalTemplateContext';
39
+ import { logRuntimeError } from '../shared/errorLogger';
21
40
 
22
41
  // Re-export for backward compatibility
23
42
  export { isResponsiveStyle };
@@ -36,7 +55,7 @@ export function normalizeStyle(style: StyleValue | null | undefined): StyleObjec
36
55
  */
37
56
  function addProcessedItemToArray(
38
57
  item: ComponentNode | (ComponentNode | string)[] | string | number | Record<string, unknown> | null,
39
- array: Array<ComponentNode | string>
58
+ array: Array<ComponentNode | string>,
40
59
  ): void {
41
60
  if (item === null) return;
42
61
 
@@ -66,7 +85,11 @@ export function isLinkMapping(value: unknown): value is LinkMapping {
66
85
  if (!value || typeof value !== 'object') return false;
67
86
  const obj = value as Record<string, unknown>;
68
87
  // values is optional - when empty/missing, acts as passthrough for link-type props
69
- return obj._mapping === true && typeof obj.prop === 'string' && (obj.values === undefined || typeof obj.values === 'object');
88
+ return (
89
+ obj._mapping === true &&
90
+ typeof obj.prop === 'string' &&
91
+ (obj.values === undefined || typeof obj.values === 'object')
92
+ );
70
93
  }
71
94
 
72
95
  /**
@@ -95,7 +118,7 @@ export function isLinkMapping(value: unknown): value is LinkMapping {
95
118
  */
96
119
  export function resolveLinkMapping(
97
120
  mappingObj: unknown,
98
- props: Record<string, unknown> | undefined
121
+ props: Record<string, unknown> | undefined,
99
122
  ): { href: string; target?: string } | undefined {
100
123
  if (!isLinkMapping(mappingObj)) {
101
124
  return undefined;
@@ -147,7 +170,7 @@ export function isHtmlMapping(value: unknown): value is HtmlMapping {
147
170
  */
148
171
  export function resolveHtmlMapping(
149
172
  mappingObj: unknown,
150
- props: Record<string, unknown> | undefined
173
+ props: Record<string, unknown> | undefined,
151
174
  ): string | undefined {
152
175
  if (!isHtmlMapping(mappingObj)) {
153
176
  return undefined;
@@ -187,14 +210,14 @@ export function resolveHtmlMapping(
187
210
  */
188
211
  export function resolveStyleMapping(
189
212
  mappingObj: unknown,
190
- props: Record<string, unknown> | undefined
213
+ props: Record<string, unknown> | undefined,
191
214
  ): string | number | undefined {
192
215
  if (!mappingObj || typeof mappingObj !== 'object') {
193
216
  return undefined;
194
217
  }
195
218
 
196
219
  const mapping = mappingObj as StyleMapping;
197
- if (!mapping || !mapping._mapping) {
220
+ if (!mapping?._mapping) {
198
221
  return undefined;
199
222
  }
200
223
 
@@ -227,7 +250,7 @@ export function resolveStyleMapping(
227
250
  */
228
251
  function processStyleValue(
229
252
  styleValue: unknown,
230
- props: Record<string, unknown> | undefined
253
+ props: Record<string, unknown> | undefined,
231
254
  ): string | number | undefined {
232
255
  // First try style mapping resolution
233
256
  const resolved = resolveStyleMapping(styleValue, props);
@@ -259,10 +282,7 @@ function processStyleValue(
259
282
  * @param includeItemContext - Whether to include itemContext from the context object
260
283
  * @returns A flat object suitable for template evaluation
261
284
  */
262
- function buildEvalContext(
263
- context: TemplateContext,
264
- includeItemContext: boolean = false
265
- ): Record<string, unknown> {
285
+ function buildEvalContext(context: TemplateContext, includeItemContext: boolean = false): Record<string, unknown> {
266
286
  // Layer order (lowest → highest precedence): global → parent component
267
287
  // props → this component's own props. The middle layer lets a `{{x}}` in
268
288
  // a child component's structure cascade to the host's `x` when the child
@@ -270,7 +290,7 @@ function buildEvalContext(
270
290
  const evalContext: Record<string, unknown> = {
271
291
  ...getGlobalTemplateContext(),
272
292
  ...(context.parentProps ?? {}),
273
- ...context.props
293
+ ...context.props,
274
294
  };
275
295
 
276
296
  if (context.componentDef && typeof context.componentDef === 'object') {
@@ -306,30 +326,39 @@ const MAX_RECURSION_DEPTH = 100;
306
326
  * evaluateTemplate("{{count + 1}}", { count: 5 }) // 6
307
327
  * evaluateTemplate("{{undefinedVar}}", {}) // undefined (no error thrown)
308
328
  */
309
- export function evaluateTemplate(
310
- template: string,
311
- context: Record<string, unknown>
312
- ): unknown {
329
+ export function evaluateTemplate(template: string, context: Record<string, unknown>): unknown {
313
330
  if (typeof template !== 'string') return template;
314
331
 
315
332
  const templateMatch = template.match(/^\{\{(.+)\}\}$/);
316
333
  if (!templateMatch) return template;
317
334
 
318
- const expression = templateMatch[1].trim();
335
+ const expression = (templateMatch[1] ?? '').trim();
319
336
 
320
337
  // Security: Expression length limit to prevent DoS
321
338
  if (expression.length > MAX_EXPRESSION_LENGTH) {
322
- console.warn('Template expression too long:', expression.slice(0, 50) + '...');
339
+ console.warn('Template expression too long:', `${expression.slice(0, 50)}...`);
323
340
  return template;
324
341
  }
325
342
 
326
343
  try {
327
344
  // Use safe expression evaluator (jsep-based, no eval/new Function)
328
345
  const result = safeEvaluate(expression, context);
329
- // If result is undefined, return template string for backward compatibility
330
- return result === undefined ? template : result;
346
+ // undefined (unknown identifier) AND NaN (arithmetic over an identifier that isn't
347
+ // in context e.g. a loop-var stagger like {{0.4+itemIndex*0.2}} evaluated by the
348
+ // props pass before the per-item pass) both mean "can't resolve here": return the
349
+ // template string so a later pass (item/CMS context) can still resolve it, and so
350
+ // React never receives a NaN attribute/prop ("Received NaN for the `fade` attribute").
351
+ if (result === undefined || (typeof result === 'number' && Number.isNaN(result))) {
352
+ return template;
353
+ }
354
+ return result;
331
355
  } catch (error) {
332
- console.error('Template evaluation error:', error, 'Expression:', expression, 'Context:', context);
356
+ // Log the expression + context key names only — never the values, which
357
+ // carry props/CMS data. Dev-gated via logRuntimeError so production stays quiet.
358
+ logRuntimeError('templateEngine.evaluateTemplate', error, {
359
+ expression: expression.slice(0, 80),
360
+ contextKeys: context ? Object.keys(context) : [],
361
+ });
333
362
  // Return original template string on error for backward compatibility
334
363
  return template;
335
364
  }
@@ -346,18 +375,15 @@ export function hasTemplates(code: string): boolean {
346
375
  /**
347
376
  * Processes template strings in JavaScript or CSS code
348
377
  * Replaces {{propName}} or {{expression}} with evaluated values
349
- *
378
+ *
350
379
  * @example
351
380
  * processCodeTemplates("console.log('{{name}}');", { name: "John" })
352
381
  * // "console.log('John');"
353
- *
382
+ *
354
383
  * processCodeTemplates(".card { color: {{color}}; }", { color: "#ff0000" })
355
384
  * // ".card { color: #ff0000; }"
356
385
  */
357
- export function processCodeTemplates(
358
- code: string,
359
- context: Record<string, unknown> | undefined
360
- ): string {
386
+ export function processCodeTemplates(code: string, context: Record<string, unknown> | undefined): string {
361
387
  if (typeof code !== 'string') return code;
362
388
 
363
389
  // Guard against undefined context
@@ -371,7 +397,7 @@ export function processCodeTemplates(
371
397
 
372
398
  // Security: Expression length limit to prevent DoS
373
399
  if (trimmedExpr.length > MAX_EXPRESSION_LENGTH) {
374
- console.warn('Code template expression too long:', trimmedExpr.slice(0, 50) + '...');
400
+ console.warn('Code template expression too long:', `${trimmedExpr.slice(0, 50)}...`);
375
401
  return match;
376
402
  }
377
403
 
@@ -396,7 +422,12 @@ export function processCodeTemplates(
396
422
  // For objects/arrays, stringify them
397
423
  return JSON.stringify(result);
398
424
  } catch (error) {
399
- console.error('Code template evaluation error:', error, 'Expression:', trimmedExpr, 'Context:', context);
425
+ // Log the expression + context key names only — never the values, which
426
+ // carry props/CMS data. Dev-gated via logRuntimeError so production stays quiet.
427
+ logRuntimeError('templateEngine.processCodeTemplates', error, {
428
+ expression: trimmedExpr.slice(0, 80),
429
+ contextKeys: context ? Object.keys(context) : [],
430
+ });
400
431
  // Return original template if evaluation fails
401
432
  return match;
402
433
  }
@@ -417,12 +448,14 @@ export function processStructure(
417
448
  viewportWidth?: number,
418
449
  instanceChildren?: ComponentNode['children'],
419
450
  preserveResponsiveStyles: boolean = false,
420
- depth: number = 0
451
+ depth: number = 0,
421
452
  ): ComponentNode | (ComponentNode | string)[] | string | number | Record<string, unknown> | null {
422
453
  try {
423
454
  // Guard against excessive recursion (circular references or very deep structures)
424
455
  if (depth > MAX_RECURSION_DEPTH) {
425
- console.warn(`processStructure: Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded. Possible circular reference.`);
456
+ console.warn(
457
+ `processStructure: Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded. Possible circular reference.`,
458
+ );
426
459
  return null;
427
460
  }
428
461
 
@@ -472,7 +505,7 @@ export function processStructure(
472
505
  // No templates - return as-is
473
506
  return structure;
474
507
  }
475
-
508
+
476
509
  if (Array.isArray(structure)) {
477
510
  const processed: Array<ComponentNode | string> = [];
478
511
  for (const item of structure) {
@@ -482,7 +515,14 @@ export function processStructure(
482
515
  if (instanceChildren) {
483
516
  const childrenArray = Array.isArray(instanceChildren) ? instanceChildren : [instanceChildren];
484
517
  for (const child of childrenArray) {
485
- const processedChild = processStructure(child, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);
518
+ const processedChild = processStructure(
519
+ child,
520
+ context,
521
+ viewportWidth,
522
+ instanceChildren,
523
+ preserveResponsiveStyles,
524
+ depth + 1,
525
+ );
486
526
  addProcessedItemToArray(processedChild, processed);
487
527
  }
488
528
  } else if ('default' in item && (item as SlotMarker).default !== undefined) {
@@ -490,20 +530,34 @@ export function processStructure(
490
530
  const defaultContent = (item as SlotMarker).default;
491
531
  const defaultsArray = Array.isArray(defaultContent) ? defaultContent : [defaultContent];
492
532
  for (const defaultChild of defaultsArray) {
493
- const processedChild = processStructure(defaultChild, context, viewportWidth, undefined, preserveResponsiveStyles, depth + 1);
533
+ const processedChild = processStructure(
534
+ defaultChild,
535
+ context,
536
+ viewportWidth,
537
+ undefined,
538
+ preserveResponsiveStyles,
539
+ depth + 1,
540
+ );
494
541
  addProcessedItemToArray(processedChild, processed);
495
542
  }
496
543
  }
497
544
  // If no instance children AND no default, marker renders nothing (skip it)
498
545
  } else {
499
546
  // Regular item - process normally
500
- const processedItem = processStructure(item, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);
547
+ const processedItem = processStructure(
548
+ item,
549
+ context,
550
+ viewportWidth,
551
+ instanceChildren,
552
+ preserveResponsiveStyles,
553
+ depth + 1,
554
+ );
501
555
  addProcessedItemToArray(processedItem, processed);
502
556
  }
503
557
  }
504
558
  return processed;
505
559
  }
506
-
560
+
507
561
  if (typeof structure === 'object' && !Array.isArray(structure) && structure !== null) {
508
562
  // Check if this is a slot marker (shouldn't happen here since we handle it in array processing, but guard anyway)
509
563
  if (isSlotMarker(structure)) {
@@ -512,10 +566,17 @@ export function processStructure(
512
566
  const processed: Array<ComponentNode | string> = [];
513
567
  const childrenArray = Array.isArray(instanceChildren) ? instanceChildren : [instanceChildren];
514
568
  for (const child of childrenArray) {
515
- const processedChild = processStructure(child, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);
569
+ const processedChild = processStructure(
570
+ child,
571
+ context,
572
+ viewportWidth,
573
+ instanceChildren,
574
+ preserveResponsiveStyles,
575
+ depth + 1,
576
+ );
516
577
  addProcessedItemToArray(processedChild, processed);
517
578
  }
518
- return processed.length === 1 ? processed[0] : processed;
579
+ return processed.length === 1 ? (processed[0] ?? processed) : processed;
519
580
  }
520
581
  // Fallback: use slot's default content
521
582
  if ('default' in structure && (structure as SlotMarker).default !== undefined) {
@@ -523,14 +584,21 @@ export function processStructure(
523
584
  const processed: Array<ComponentNode | string> = [];
524
585
  const defaultsArray = Array.isArray(defaultContent) ? defaultContent : [defaultContent];
525
586
  for (const defaultChild of defaultsArray) {
526
- const processedChild = processStructure(defaultChild, context, viewportWidth, undefined, preserveResponsiveStyles, depth + 1);
587
+ const processedChild = processStructure(
588
+ defaultChild,
589
+ context,
590
+ viewportWidth,
591
+ undefined,
592
+ preserveResponsiveStyles,
593
+ depth + 1,
594
+ );
527
595
  addProcessedItemToArray(processedChild, processed);
528
596
  }
529
- return processed.length === 1 ? processed[0] : processed;
597
+ return processed.length === 1 ? (processed[0] ?? processed) : processed;
530
598
  }
531
599
  return null;
532
600
  }
533
-
601
+
534
602
  // Check if this is a valid node structure or a plain object (like props)
535
603
  const inputNode = structure as ComponentNode;
536
604
  const hasValidNodeType = inputNode.type && isValidNodeType(inputNode.type);
@@ -540,7 +608,14 @@ export function processStructure(
540
608
  if (!hasValidNodeType) {
541
609
  const result: Record<string, unknown> = {};
542
610
  for (const [key, value] of Object.entries(structure)) {
543
- const processedValue = processStructure(value as ComponentNode | string | number | null, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);
611
+ const processedValue = processStructure(
612
+ value as ComponentNode | string | number | null,
613
+ context,
614
+ viewportWidth,
615
+ instanceChildren,
616
+ preserveResponsiveStyles,
617
+ depth + 1,
618
+ );
544
619
  if (processedValue !== null && processedValue !== undefined) {
545
620
  result[key] = processedValue;
546
621
  }
@@ -557,7 +632,7 @@ export function processStructure(
557
632
  type: NODE_TYPE.COMPONENT,
558
633
  component: '',
559
634
  props: {},
560
- children: [] as Array<ComponentNode | string>
635
+ children: [] as Array<ComponentNode | string>,
561
636
  } as ComponentInstanceNode;
562
637
  } else if (preservedType === NODE_TYPE.EMBED) {
563
638
  // Handle embed nodes - they have html content, not children
@@ -570,7 +645,7 @@ export function processStructure(
570
645
  processed = {
571
646
  type: NODE_TYPE.LINK,
572
647
  href: '',
573
- children: [] as Array<ComponentNode | string>
648
+ children: [] as Array<ComponentNode | string>,
574
649
  } as unknown as ComponentNode;
575
650
  } else if (preservedType === NODE_TYPE.LOCALE_LIST) {
576
651
  // Handle locale-list nodes - they have style, itemStyle, activeItemStyle properties
@@ -583,23 +658,30 @@ export function processStructure(
583
658
  processed = {
584
659
  type: NODE_TYPE.LIST,
585
660
  source: '',
586
- children: [] as Array<ComponentNode | string>
661
+ children: [] as Array<ComponentNode | string>,
587
662
  } as unknown as ComponentNode;
588
663
  } else {
589
664
  processed = {
590
665
  type: NODE_TYPE.NODE,
591
666
  tag: 'div',
592
- children: [] as Array<ComponentNode | string>
667
+ children: [] as Array<ComponentNode | string>,
593
668
  } as HtmlNode;
594
669
  }
595
-
670
+
596
671
  // First pass: process all keys and resolve style mappings
597
672
  let resolvedStyle: StyleValue | null = null;
598
-
673
+
599
674
  for (const [key, value] of Object.entries(structure)) {
600
675
  try {
601
676
  if (key === 'children') {
602
- const processedChildren = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);
677
+ const processedChildren = processStructure(
678
+ value as ComponentNode | ComponentNode[] | string | number | null | undefined,
679
+ context,
680
+ viewportWidth,
681
+ instanceChildren,
682
+ preserveResponsiveStyles,
683
+ depth + 1,
684
+ );
603
685
  if (Array.isArray(processedChildren)) {
604
686
  processed.children = processedChildren;
605
687
  } else if (processedChildren !== null && processedChildren !== undefined) {
@@ -648,7 +730,11 @@ export function processStructure(
648
730
  } else {
649
731
  processed.html = value;
650
732
  }
651
- } else if (typeof value === 'object' && value !== null && (value as Record<string, unknown>)._mapping === true) {
733
+ } else if (
734
+ typeof value === 'object' &&
735
+ value !== null &&
736
+ (value as Record<string, unknown>)._mapping === true
737
+ ) {
652
738
  // HtmlMapping object that isHtmlMapping somehow missed — resolve it defensively
653
739
  const resolved = resolveHtmlMapping(value, context.props);
654
740
  processed.html = resolved ?? '';
@@ -668,7 +754,7 @@ export function processStructure(
668
754
  component: '',
669
755
  props: (p.props || {}) as ComponentInstanceNode['props'],
670
756
  children: p.children as ComponentInstanceNode['children'],
671
- style: p.style as ComponentInstanceNode['style']
757
+ style: p.style as ComponentInstanceNode['style'],
672
758
  };
673
759
  processed = newProcessed;
674
760
  } else if (value === NODE_TYPE.NODE && !isHtmlNode(processed)) {
@@ -678,7 +764,7 @@ export function processStructure(
678
764
  type: NODE_TYPE.NODE,
679
765
  tag: (p.component as string) || 'div',
680
766
  children: p.children as HtmlNode['children'],
681
- style: p.style as HtmlNode['style']
767
+ style: p.style as HtmlNode['style'],
682
768
  };
683
769
  processed = newProcessed;
684
770
  }
@@ -691,9 +777,9 @@ export function processStructure(
691
777
  if (processedStyle && typeof processedStyle === 'object' && !Array.isArray(processedStyle)) {
692
778
  // Check if it's a responsive style object
693
779
  const styleEvalContext = buildEvalContext(context, false);
694
- if (isResponsiveStyle(processedStyle as StyleValue)) {
780
+ if (isResponsiveStyle(processedStyle as StyleValue)) {
695
781
  // Preserve responsive styles (for both SSR and editor)
696
- // responsiveStylesToClasses will generate prefixed classes (t-, mob-)
782
+ // responsiveStylesToClasses will generate prefixed classes (tablet:, mobile:)
697
783
  // CSS media queries will handle displaying the correct styles based on viewport
698
784
  const resolvedResponsive: ResponsiveStyleObject = {};
699
785
  for (const [bkeyName, bkeyValue] of Object.entries(processedStyle)) {
@@ -721,9 +807,21 @@ export function processStructure(
721
807
  }
722
808
  } else if (key === 'props' && typeof value === 'object' && value !== null) {
723
809
  // Process non-style props (for instance props only)
724
- const processedProps = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);
810
+ const processedProps = processStructure(
811
+ value as ComponentNode | ComponentNode[] | string | number | null | undefined,
812
+ context,
813
+ viewportWidth,
814
+ instanceChildren,
815
+ preserveResponsiveStyles,
816
+ depth + 1,
817
+ );
725
818
  // Merge non-style props (style is handled separately at top level)
726
- if (typeof processedProps === 'object' && !Array.isArray(processedProps) && processedProps !== null && processed.props) {
819
+ if (
820
+ typeof processedProps === 'object' &&
821
+ !Array.isArray(processedProps) &&
822
+ processedProps !== null &&
823
+ processed.props
824
+ ) {
727
825
  const propsObj = processedProps as unknown as Record<string, unknown>;
728
826
  Object.assign(processed.props, propsObj);
729
827
  // Remove style from props since we handle it at top level
@@ -744,7 +842,7 @@ export function processStructure(
744
842
  if (resolved.target) {
745
843
  pLink.attributes = {
746
844
  ...((pLink.attributes as Record<string, unknown>) || {}),
747
- target: resolved.target
845
+ target: resolved.target,
748
846
  };
749
847
  }
750
848
  } else {
@@ -752,13 +850,24 @@ export function processStructure(
752
850
  }
753
851
  } else {
754
852
  // Regular href value - process as template
755
- const processedValue = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);
853
+ const processedValue = processStructure(
854
+ value as ComponentNode | ComponentNode[] | string | number | null | undefined,
855
+ context,
856
+ viewportWidth,
857
+ instanceChildren,
858
+ preserveResponsiveStyles,
859
+ depth + 1,
860
+ );
756
861
  if (processedValue !== null && processedValue !== undefined) {
757
862
  // Check if result is a link object (from link-type prop like {{link}})
758
863
  if (typeof processedValue === 'object' && processedValue !== null && 'href' in processedValue) {
759
864
  // Unwrap nested link objects (e.g., {href: {href: "/path"}} from double-wrapped list item templates)
760
865
  let linkObj = processedValue as { href: unknown; target?: string };
761
- while (typeof linkObj.href === 'object' && linkObj.href !== null && 'href' in (linkObj.href as Record<string, unknown>)) {
866
+ while (
867
+ typeof linkObj.href === 'object' &&
868
+ linkObj.href !== null &&
869
+ 'href' in (linkObj.href as Record<string, unknown>)
870
+ ) {
762
871
  const nested = linkObj.href as { href: unknown; target?: string };
763
872
  if (!linkObj.target && nested.target) linkObj = { ...linkObj, target: nested.target };
764
873
  linkObj = { ...linkObj, href: nested.href };
@@ -767,7 +876,7 @@ export function processStructure(
767
876
  if (linkObj.target) {
768
877
  pLink.attributes = {
769
878
  ...((pLink.attributes as Record<string, unknown>) || {}),
770
- target: linkObj.target
879
+ target: linkObj.target,
771
880
  };
772
881
  }
773
882
  } else {
@@ -819,15 +928,31 @@ export function processStructure(
819
928
  context.props &&
820
929
  Array.isArray((context.props as Record<string, unknown>)[value])
821
930
  ) {
822
- (processed as unknown as Record<string, unknown>).source = (context.props as Record<string, unknown>)[value];
931
+ (processed as unknown as Record<string, unknown>).source = (context.props as Record<string, unknown>)[
932
+ value
933
+ ];
823
934
  } else {
824
- const processedValue = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);
935
+ const processedValue = processStructure(
936
+ value as ComponentNode | ComponentNode[] | string | number | null | undefined,
937
+ context,
938
+ viewportWidth,
939
+ instanceChildren,
940
+ preserveResponsiveStyles,
941
+ depth + 1,
942
+ );
825
943
  if (processedValue !== null && processedValue !== undefined) {
826
944
  (processed as unknown as Record<string, unknown>).source = processedValue;
827
945
  }
828
946
  }
829
947
  } else if (key !== 'type' && key !== 'children' && key !== 'style' && key !== 'props') {
830
- const processedValue = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);
948
+ const processedValue = processStructure(
949
+ value as ComponentNode | ComponentNode[] | string | number | null | undefined,
950
+ context,
951
+ viewportWidth,
952
+ instanceChildren,
953
+ preserveResponsiveStyles,
954
+ depth + 1,
955
+ );
831
956
  // Only assign if it's a valid value
832
957
  if (processedValue !== null && processedValue !== undefined) {
833
958
  // Store extra properties on the node object
@@ -839,7 +964,7 @@ export function processStructure(
839
964
  // Continue processing other keys
840
965
  }
841
966
  }
842
-
967
+
843
968
  // Apply resolved styles to the processed node based on its type
844
969
  // Both SSR and Editor now preserve responsive styles for proper utility class generation
845
970
  if (resolvedStyle && Object.keys(resolvedStyle).length > 0) {
@@ -847,7 +972,13 @@ export function processStructure(
847
972
  // Apply responsive styles directly to node.style or props.style
848
973
  if (isComponentNode(processed)) {
849
974
  (processed as unknown as Record<string, unknown>).style = resolvedStyle as ResponsiveStyleObject;
850
- } else if (isHtmlNode(processed) || isEmbedNode(processed) || isLocaleListNode(processed) || isLinkNode(processed) || isListNode(processed)) {
975
+ } else if (
976
+ isHtmlNode(processed) ||
977
+ isEmbedNode(processed) ||
978
+ isLocaleListNode(processed) ||
979
+ isLinkNode(processed) ||
980
+ isListNode(processed)
981
+ ) {
851
982
  processed.style = resolvedStyle as ResponsiveStyleObject;
852
983
  }
853
984
  } else {
@@ -855,14 +986,13 @@ export function processStructure(
855
986
  applyStylesToNode(processed, resolvedStyle);
856
987
  }
857
988
  }
858
-
989
+
859
990
  return processed;
860
991
  }
861
-
992
+
862
993
  return structure;
863
994
  } catch (error) {
864
995
  console.error('Error in processStructure:', error);
865
996
  throw error; // Re-throw so it can be caught by error boundary
866
997
  }
867
998
  }
868
-
@@ -1,5 +1,5 @@
1
1
  import { describe, test, expect } from 'bun:test';
2
- import { getThemeColors, type Theme, type ThemeColors } from './theme';
2
+ import { getThemeColors } from './theme';
3
3
 
4
4
  describe('theme', () => {
5
5
  describe('getThemeColors', () => {
@@ -147,4 +147,3 @@ const darkThemeColors: ThemeColors = {
147
147
  export function getThemeColors(theme: Theme): ThemeColors {
148
148
  return theme === 'light' ? lightThemeColors : darkThemeColors;
149
149
  }
150
-
@@ -44,4 +44,3 @@ export function showApiErrorToast(error: Error, _duration?: number): void {
44
44
  const message = error.message || 'An unexpected error occurred';
45
45
  showErrorToast(message, _duration);
46
46
  }
47
-
@@ -15,10 +15,14 @@ beforeAll(async () => {
15
15
  ctx = await createTestServer({
16
16
  pages: {
17
17
  '/': TEST_PAGE_JSON,
18
- '/about': JSON.stringify({
19
- meta: { title: 'About', description: 'About page' },
20
- root: { type: 'node', tag: 'div', children: 'About content' },
21
- }, null, 2),
18
+ '/about': JSON.stringify(
19
+ {
20
+ meta: { title: 'About', description: 'About page' },
21
+ root: { type: 'node', tag: 'div', children: 'About content' },
22
+ },
23
+ null,
24
+ 2,
25
+ ),
22
26
  },
23
27
  components,
24
28
  });
@@ -40,10 +40,7 @@ beforeAll(async () => {
40
40
  setProjectRoot(tempProject.projectDir);
41
41
 
42
42
  // Create CMS provider and service with real file system
43
- const cmsProvider = new FileSystemCMSProvider(
44
- `${tempProject.projectDir}/templates`,
45
- `${tempProject.projectDir}/cms`
46
- );
43
+ const cmsProvider = new FileSystemCMSProvider(`${tempProject.projectDir}/templates`, `${tempProject.projectDir}/cms`);
47
44
  const cmsService = new CMSService(cmsProvider);
48
45
  await cmsService.initialize();
49
46