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
@@ -4,11 +4,7 @@
4
4
  * Uses exact-match table for common values, arbitrary value fallback for the rest.
5
5
  */
6
6
 
7
- import type {
8
- StyleObject,
9
- ResponsiveStyleObject,
10
- StyleMapping,
11
- } from '../../shared/types/styles';
7
+ import type { StyleObject, ResponsiveStyleObject, StyleMapping } from '../../shared/types/styles';
12
8
  import type { BreakpointConfig } from '../../shared/breakpoints';
13
9
  import type { ResponsiveScales, CSSPropertyType } from '../../shared/responsiveScaling';
14
10
  import { getScaleMultiplier, scalePropertyValue } from '../../shared/responsiveScaling';
@@ -19,10 +15,7 @@ import { getScaleMultiplier, scalePropertyValue } from '../../shared/responsiveS
19
15
 
20
16
  function isStyleMapping(value: unknown): value is StyleMapping {
21
17
  return (
22
- typeof value === 'object' &&
23
- value !== null &&
24
- '_mapping' in value &&
25
- (value as StyleMapping)._mapping === true
18
+ typeof value === 'object' && value !== null && '_mapping' in value && (value as StyleMapping)._mapping === true
26
19
  );
27
20
  }
28
21
 
@@ -30,9 +23,7 @@ function hasTemplateExpression(value: string): boolean {
30
23
  return /\{\{.+?\}\}/.test(value);
31
24
  }
32
25
 
33
- function isResponsiveStyle(
34
- style: StyleObject | ResponsiveStyleObject
35
- ): style is ResponsiveStyleObject {
26
+ function isResponsiveStyle(style: StyleObject | ResponsiveStyleObject): style is ResponsiveStyleObject {
36
27
  return 'base' in style || 'tablet' in style || 'mobile' in style;
37
28
  }
38
29
 
@@ -390,10 +381,7 @@ const arbitraryPrefixMap: Record<string, string> = {
390
381
  * Convert a single CSS property:value pair to a Tailwind class.
391
382
  * Returns null if the value should be skipped (mappings, templates).
392
383
  */
393
- export function propertyToTailwind(
394
- property: string,
395
- value: string | number
396
- ): string | null {
384
+ export function propertyToTailwind(property: string, value: string | number): string | null {
397
385
  const strValue = String(value);
398
386
 
399
387
  // Skip empty values — they produce broken classes like gap-[], mt-[]
@@ -436,9 +424,19 @@ export function propertyToTailwind(
436
424
 
437
425
  // Border shorthand (e.g., "1px solid", "2px solid var(--border)") needs arbitrary property syntax
438
426
  // because Tailwind's border-[...] only accepts width values, not compound shorthands
439
- if (property === 'border' || property === 'borderTop' || property === 'borderRight' ||
440
- property === 'borderBottom' || property === 'borderLeft') {
441
- if (strValue.includes('solid') || strValue.includes('dashed') || strValue.includes('dotted') || strValue.includes('none')) {
427
+ if (
428
+ property === 'border' ||
429
+ property === 'borderTop' ||
430
+ property === 'borderRight' ||
431
+ property === 'borderBottom' ||
432
+ property === 'borderLeft'
433
+ ) {
434
+ if (
435
+ strValue.includes('solid') ||
436
+ strValue.includes('dashed') ||
437
+ strValue.includes('dotted') ||
438
+ strValue.includes('none')
439
+ ) {
442
440
  const cssProp = property.replace(/([A-Z])/g, '-$1').toLowerCase();
443
441
  const sanitized = strValue.replace(/\s+/g, '_');
444
442
  return `[${cssProp}:${sanitized}]`;
@@ -494,9 +492,10 @@ export function propertyToTailwind(
494
492
  * Returns { classes, dynamicStyles } where dynamicStyles are template-expression
495
493
  * styles that need inline style attributes.
496
494
  */
497
- export function stylesToTailwind(
498
- style: StyleObject | Record<string, string | number>
499
- ): { classes: string[]; dynamicStyles: Record<string, string> } {
495
+ export function stylesToTailwind(style: StyleObject | Record<string, string | number>): {
496
+ classes: string[];
497
+ dynamicStyles: Record<string, string>;
498
+ } {
500
499
  const classes: string[] = [];
501
500
  const dynamicStyles: Record<string, string> = {};
502
501
 
@@ -506,9 +505,7 @@ export function stylesToTailwind(
506
505
  // border shorthands into width + style only (dropping the color part) so
507
506
  // borderColor can take effect without conflicts.
508
507
  const hasBorderColor = 'borderColor' in style && !isStyleMapping(style.borderColor);
509
- const borderShorthands = new Set([
510
- 'border', 'borderTop', 'borderRight', 'borderBottom', 'borderLeft',
511
- ]);
508
+ const borderShorthands = new Set(['border', 'borderTop', 'borderRight', 'borderBottom', 'borderLeft']);
512
509
 
513
510
  for (const [prop, value] of Object.entries(style)) {
514
511
  if (isStyleMapping(value)) continue;
@@ -526,8 +523,10 @@ export function stylesToTailwind(
526
523
  if (hasBorderColor && borderShorthands.has(prop)) {
527
524
  const parts = strValue.split(/\s+/);
528
525
  // Parse width and style from shorthand (e.g. "1px solid #ccc" → "1px", "solid")
529
- const width = parts.find(p => /^\d/.test(p) || p === '0');
530
- const borderStyle = parts.find(p => /^(solid|dashed|dotted|double|groove|ridge|inset|outset|none|hidden)$/.test(p));
526
+ const width = parts.find((p) => /^\d/.test(p) || p === '0');
527
+ const borderStyle = parts.find((p) =>
528
+ /^(solid|dashed|dotted|double|groove|ridge|inset|outset|none|hidden)$/.test(p),
529
+ );
531
530
  const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
532
531
  if (width) classes.push(`[${cssProp}-width:${width}]`);
533
532
  if (borderStyle) classes.push(`[${cssProp}-style:${borderStyle}]`);
@@ -554,7 +553,7 @@ export function stylesToTailwind(
554
553
  export function responsiveStylesToTailwind(
555
554
  style: StyleObject | ResponsiveStyleObject | null | undefined,
556
555
  breakpoints: BreakpointConfig,
557
- responsiveScales?: ResponsiveScales
556
+ responsiveScales?: ResponsiveScales,
558
557
  ): { classes: string[]; dynamicStyles: Record<string, string> } {
559
558
  if (!style) return { classes: [], dynamicStyles: {} };
560
559
 
@@ -576,7 +575,7 @@ export function responsiveStylesToTailwind(
576
575
  const bpValue = breakpoints.tablet?.breakpoint ?? 1024;
577
576
  const prefix = `max-[${bpValue}px]:`;
578
577
  const { classes, dynamicStyles } = stylesToTailwind(responsive.tablet);
579
- allClasses.push(...classes.map(cls => `${prefix}${cls}`));
578
+ allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
580
579
  // Dynamic styles for tablet — just merge (can't do responsive inline styles easily)
581
580
  Object.assign(allDynamicStyles, dynamicStyles);
582
581
  }
@@ -586,7 +585,7 @@ export function responsiveStylesToTailwind(
586
585
  const bpValue = breakpoints.mobile?.breakpoint ?? 540;
587
586
  const prefix = `max-[${bpValue}px]:`;
588
587
  const { classes, dynamicStyles } = stylesToTailwind(responsive.mobile);
589
- allClasses.push(...classes.map(cls => `${prefix}${cls}`));
588
+ allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
590
589
  Object.assign(allDynamicStyles, dynamicStyles);
591
590
  }
592
591
 
@@ -597,7 +596,7 @@ export function responsiveStylesToTailwind(
597
596
  if (!bpValue) continue;
598
597
  const prefix = `max-[${bpValue}px]:`;
599
598
  const { classes, dynamicStyles } = stylesToTailwind(bpStyle);
600
- allClasses.push(...classes.map(cls => `${prefix}${cls}`));
599
+ allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
601
600
  Object.assign(allDynamicStyles, dynamicStyles);
602
601
  }
603
602
 
@@ -629,7 +628,7 @@ function appendAutoScaledClasses(
629
628
  responsive: ResponsiveStyleObject,
630
629
  breakpoints: BreakpointConfig,
631
630
  responsiveScales: ResponsiveScales,
632
- out: string[]
631
+ out: string[],
633
632
  ): void {
634
633
  const base = responsive.base;
635
634
  if (!base) return;
@@ -638,9 +637,7 @@ function appendAutoScaledClasses(
638
637
 
639
638
  const sortedBps = Object.entries(breakpoints)
640
639
  .map(([name, cfg]) => ({ name, value: cfg?.breakpoint }))
641
- .filter((bp): bp is { name: string; value: number } =>
642
- typeof bp.value === 'number' && bp.value > 0
643
- )
640
+ .filter((bp): bp is { name: string; value: number } => typeof bp.value === 'number' && bp.value > 0)
644
641
  .sort((a, b) => b.value - a.value);
645
642
 
646
643
  for (const [property, value] of Object.entries(base)) {
@@ -655,11 +652,7 @@ function appendAutoScaledClasses(
655
652
  const bpBranch = responsive[bpName] as StyleObject | undefined;
656
653
  if (bpBranch && property in bpBranch) continue;
657
654
 
658
- const scale = getScaleMultiplier(
659
- responsiveScales,
660
- property as CSSPropertyType,
661
- bpName
662
- );
655
+ const scale = getScaleMultiplier(responsiveScales, property as CSSPropertyType, bpName);
663
656
  if (scale == null) continue;
664
657
 
665
658
  const scaledValue = scalePropertyValue(strValue, baseRef, scale);
@@ -3,11 +3,6 @@
3
3
  * Converts {{cms.field}} and {{item.field}} template expressions to Astro expressions
4
4
  */
5
5
 
6
- // CMS template pattern (from cmsSSRProcessor.ts)
7
- const CMS_TEMPLATE_PATTERN = /\{\{cms\.([^}]+)\}\}/g;
8
- // Item template pattern for list iteration
9
- const ITEM_TEMPLATE_PATTERN = /\{\{([^}]+)\}\}/g;
10
-
11
6
  export function isTemplateExpression(text: string): boolean {
12
7
  return /\{\{.+?\}\}/.test(text);
13
8
  }
@@ -16,15 +11,15 @@ export function transformCMSTemplate(
16
11
  text: string,
17
12
  binding: string = 'entry',
18
13
  richTextFields?: Set<string>,
19
- wrapFn?: string
14
+ wrapFn?: string,
20
15
  ): string {
21
- const w = (expr: string) => wrapFn ? `${wrapFn}(${expr})` : expr;
16
+ const w = (expr: string) => (wrapFn ? `${wrapFn}(${expr})` : expr);
22
17
 
23
18
  // Check if entire text is a single {{cms.field}} expression
24
19
  const fullMatch = text.match(/^\{\{cms\.([^}]+)\}\}$/);
25
20
  if (fullMatch) {
26
- const fieldPath = fullMatch[1].trim();
27
- const topLevelField = fieldPath.split('.')[0];
21
+ const fieldPath = (fullMatch[1] ?? '').trim();
22
+ const topLevelField = fieldPath.split('.')[0] ?? '';
28
23
 
29
24
  // Rich-text fields use Fragment set:html
30
25
  if (richTextFields?.has(topLevelField)) {
@@ -35,9 +30,11 @@ export function transformCMSTemplate(
35
30
  }
36
31
 
37
32
  // Mixed content: "Hello {{cms.name}}" → {`Hello ${entry.data.name}`}
38
- if (CMS_TEMPLATE_PATTERN.test(text)) {
39
- CMS_TEMPLATE_PATTERN.lastIndex = 0;
40
- const replaced = text.replace(CMS_TEMPLATE_PATTERN, (_, fieldPath) => {
33
+ // Construct the regex locally per call: a module-level /g regex carries mutable
34
+ // lastIndex state across calls (the "every-other-call" .test() footgun).
35
+ const cmsPattern = /\{\{cms\.([^}]+)\}\}/g;
36
+ if (cmsPattern.test(text)) {
37
+ const replaced = text.replace(cmsPattern, (_, fieldPath) => {
41
38
  return `\${${w(`${binding}.data.${fieldPath.trim()}`)}}`;
42
39
  });
43
40
  return `{\`${replaced}\`}`;
@@ -60,9 +57,7 @@ export function rewriteItemVar(expr: string, itemVar: string): string {
60
57
  }
61
58
 
62
59
  export function replaceItemMetaVars(expr: string, indexVar: string, sourceVar?: string, itemVar?: string): string {
63
- const lastExpr = sourceVar
64
- ? `(${indexVar} === ${sourceVar}.length - 1)`
65
- : `false /* itemLast not supported */`;
60
+ const lastExpr = sourceVar ? `(${indexVar} === ${sourceVar}.length - 1)` : `false /* itemLast not supported */`;
66
61
  let result = expr
67
62
  .replace(/\bitemIndex\b/g, indexVar)
68
63
  .replace(/\bitemFirst\b/g, `(${indexVar} === 0)`)
@@ -75,12 +70,12 @@ export function transformItemTemplate(
75
70
  text: string,
76
71
  itemVar: string = 'item',
77
72
  indexVar?: string,
78
- sourceVar?: string
73
+ sourceVar?: string,
79
74
  ): string {
80
75
  // Check if entire text is a single {{expression}}
81
76
  const fullMatch = text.match(/^\{\{(.+)\}\}$/);
82
77
  if (fullMatch) {
83
- let expr = fullMatch[1].trim();
78
+ let expr = (fullMatch[1] ?? '').trim();
84
79
  expr = rewriteItemVar(expr, itemVar);
85
80
  if (indexVar) expr = replaceItemMetaVars(expr, indexVar, sourceVar);
86
81
  // If it contains a dot, it's item.field
@@ -92,9 +87,11 @@ export function transformItemTemplate(
92
87
  }
93
88
 
94
89
  // Mixed content: replace each {{expr}}
95
- if (ITEM_TEMPLATE_PATTERN.test(text)) {
96
- ITEM_TEMPLATE_PATTERN.lastIndex = 0;
97
- const replaced = text.replace(ITEM_TEMPLATE_PATTERN, (_, expr) => {
90
+ // Construct the regex locally per call: a module-level /g regex carries mutable
91
+ // lastIndex state across calls (the "every-other-call" .test() footgun).
92
+ const itemPattern = /\{\{([^}]+)\}\}/g;
93
+ if (itemPattern.test(text)) {
94
+ const replaced = text.replace(itemPattern, (_, expr) => {
98
95
  let trimmed = expr.trim();
99
96
  trimmed = rewriteItemVar(trimmed, itemVar);
100
97
  if (indexVar) trimmed = replaceItemMetaVars(trimmed, indexVar, sourceVar);
@@ -60,11 +60,7 @@ export interface ServerConfig {
60
60
  /**
61
61
  * Additional route handler type
62
62
  */
63
- export type AdditionalRouteHandler = (
64
- req: Request,
65
- url: URL,
66
- context: RouteContext
67
- ) => Promise<Response | undefined>;
63
+ export type AdditionalRouteHandler = (req: Request, url: URL, context: RouteContext) => Promise<Response | undefined>;
68
64
 
69
65
  /**
70
66
  * Server factory result
@@ -110,7 +106,7 @@ export async function createServer(config: ServerConfig): Promise<ServerResult>
110
106
  };
111
107
 
112
108
  // Will be set after server starts to inject actual bound port into live reload script
113
- let boundPort: number | undefined;
109
+ let _boundPort: number | undefined;
114
110
 
115
111
  // Try to start server, incrementing port if busy
116
112
  let lastError: unknown;
@@ -138,17 +134,13 @@ export async function createServer(config: ServerConfig): Promise<ServerResult>
138
134
  // WebSocket upgrade for HMR
139
135
  if (url.pathname === HMR_ROUTE) {
140
136
  const success = upgradeWebSocket(req);
141
- return success
142
- ? undefined
143
- : new Response('WebSocket upgrade failed', { status: 500 });
137
+ return success ? undefined : new Response('WebSocket upgrade failed', { status: 500 });
144
138
  }
145
139
 
146
140
  // WebSocket upgrade for collab sync
147
141
  if (url.pathname === COLLAB_ROUTE && onCollabWSMessage) {
148
142
  const success = upgradeWebSocket(req);
149
- return success
150
- ? undefined
151
- : new Response('WebSocket upgrade failed', { status: 500 });
143
+ return success ? undefined : new Response('WebSocket upgrade failed', { status: 500 });
152
144
  }
153
145
 
154
146
  // Handle all routes through centralized router
@@ -176,11 +168,7 @@ export async function createServer(config: ServerConfig): Promise<ServerResult>
176
168
  }
177
169
 
178
170
  // Route collab messages to collab handler
179
- if (
180
- onCollabWSMessage &&
181
- typeof data.type === 'string' &&
182
- data.type.startsWith('collab:')
183
- ) {
171
+ if (onCollabWSMessage && typeof data.type === 'string' && data.type.startsWith('collab:')) {
184
172
  collabClients.add(ws);
185
173
  onCollabWSMessage(ws, data);
186
174
  return;
@@ -190,7 +178,7 @@ export async function createServer(config: ServerConfig): Promise<ServerResult>
190
178
  if (onWSMessage) {
191
179
  onWSMessage(ws, data);
192
180
  }
193
- } catch (error) {
181
+ } catch (_error) {
194
182
  // Ignore non-JSON messages
195
183
  }
196
184
  },
@@ -218,7 +206,7 @@ export async function createServer(config: ServerConfig): Promise<ServerResult>
218
206
  if (err?.code === 'EADDRINUSE') {
219
207
  if (portAttempt >= MAX_PORT_ATTEMPTS - 1) {
220
208
  console.error(
221
- `Failed to start server: All ports from ${requestedPort} to ${requestedPort + MAX_PORT_ATTEMPTS - 1} are busy`
209
+ `Failed to start server: All ports from ${requestedPort} to ${requestedPort + MAX_PORT_ATTEMPTS - 1} are busy`,
222
210
  );
223
211
  throw error;
224
212
  }
@@ -9,10 +9,10 @@ describe('cssGenerator', () => {
9
9
  test('should generate CSS color variables', () => {
10
10
  const colors: ColorVariables = {
11
11
  colors: {
12
- 'primary': '#3b82f6',
13
- 'secondary': '#10b981',
14
- 'text': '#1f2937'
15
- }
12
+ primary: '#3b82f6',
13
+ secondary: '#10b981',
14
+ text: '#1f2937',
15
+ },
16
16
  };
17
17
 
18
18
  const css = generateColorVariablesCSS(colors);
@@ -31,7 +31,7 @@ describe('cssGenerator', () => {
31
31
 
32
32
  test('should handle single color', () => {
33
33
  const colors: ColorVariables = {
34
- colors: { 'primary': '#ff0000' }
34
+ colors: { primary: '#ff0000' },
35
35
  };
36
36
 
37
37
  const css = generateColorVariablesCSS(colors);
@@ -43,8 +43,8 @@ describe('cssGenerator', () => {
43
43
  const colors: ColorVariables = {
44
44
  colors: {
45
45
  'primary-light': '#e0f2fe',
46
- 'text-secondary': '#6b7280'
47
- }
46
+ 'text-secondary': '#6b7280',
47
+ },
48
48
  };
49
49
 
50
50
  const css = generateColorVariablesCSS(colors);
@@ -62,18 +62,18 @@ describe('cssGenerator', () => {
62
62
  light: {
63
63
  label: 'Light',
64
64
  colors: {
65
- 'background': '#ffffff',
66
- 'text': '#000000'
67
- }
65
+ background: '#ffffff',
66
+ text: '#000000',
67
+ },
68
68
  },
69
69
  dark: {
70
70
  label: 'Dark',
71
71
  colors: {
72
- 'background': '#1f2937',
73
- 'text': '#f9fafb'
74
- }
75
- }
76
- }
72
+ background: '#1f2937',
73
+ text: '#f9fafb',
74
+ },
75
+ },
76
+ },
77
77
  };
78
78
 
79
79
  const css = generateThemeColorVariablesCSS(themeConfig);
@@ -91,9 +91,9 @@ describe('cssGenerator', () => {
91
91
  themes: {
92
92
  light: {
93
93
  label: 'Light',
94
- colors: { 'primary': '#3b82f6' }
95
- }
96
- }
94
+ colors: { primary: '#3b82f6' },
95
+ },
96
+ },
97
97
  };
98
98
 
99
99
  const css = generateThemeColorVariablesCSS(themeConfig);
@@ -108,9 +108,9 @@ describe('cssGenerator', () => {
108
108
  themes: {
109
109
  default: {
110
110
  label: 'Default',
111
- colors: { 'color': '#000000' }
112
- }
113
- }
111
+ colors: { color: '#000000' },
112
+ },
113
+ },
114
114
  };
115
115
 
116
116
  const css = generateThemeColorVariablesCSS(themeConfig);
@@ -122,7 +122,7 @@ describe('cssGenerator', () => {
122
122
  test('should handle empty themes', () => {
123
123
  const themeConfig: ThemeConfig = {
124
124
  default: 'default',
125
- themes: {}
125
+ themes: {},
126
126
  };
127
127
 
128
128
  const css = generateThemeColorVariablesCSS(themeConfig);
@@ -136,13 +136,13 @@ describe('cssGenerator', () => {
136
136
  themes: {
137
137
  light: {
138
138
  label: 'Light',
139
- colors: {}
139
+ colors: {},
140
140
  },
141
141
  dark: {
142
142
  label: 'Dark',
143
- colors: { 'primary': '#000' }
144
- }
145
- }
143
+ colors: { primary: '#000' },
144
+ },
145
+ },
146
146
  };
147
147
 
148
148
  const css = generateThemeColorVariablesCSS(themeConfig);
@@ -157,13 +157,13 @@ describe('cssGenerator', () => {
157
157
  themes: {
158
158
  light: {
159
159
  label: 'Light',
160
- colors: { 'a': '#fff' }
160
+ colors: { a: '#fff' },
161
161
  },
162
162
  dark: {
163
163
  label: 'Dark',
164
- colors: { 'b': '#000' }
165
- }
166
- }
164
+ colors: { b: '#000' },
165
+ },
166
+ },
167
167
  };
168
168
 
169
169
  const css = generateThemeColorVariablesCSS(themeConfig);
@@ -183,26 +183,19 @@ describe('cssGenerator', () => {
183
183
  };
184
184
 
185
185
  test('emits --site-margin clamp on :root when fluid mode is enabled (no user vars)', () => {
186
- const css = generateVariablesCSS(
187
- { variables: [] },
188
- DEFAULT_BREAKPOINTS,
189
- fluidScales
190
- );
186
+ const css = generateVariablesCSS({ variables: [] }, DEFAULT_BREAKPOINTS, fluidScales);
191
187
  expect(css).toContain('--site-margin: clamp(16px,');
192
188
  expect(css).toContain(', 32px)');
193
189
  expect(css).not.toContain('@media');
194
190
  });
195
191
 
196
-
197
192
  test('emits user variables with clamp() in fluid mode (no @media)', () => {
198
193
  const css = generateVariablesCSS(
199
194
  {
200
- variables: [
201
- { name: 'h1-fs', cssVar: '--h1-fs', value: '32px', type: 'fontSize' },
202
- ],
195
+ variables: [{ name: 'h1-fs', cssVar: '--h1-fs', value: '32px', type: 'fontSize' }],
203
196
  },
204
197
  DEFAULT_BREAKPOINTS,
205
- fluidScales
198
+ fluidScales,
206
199
  );
207
200
  // mobile fontSize scale=0.75 → MIN=28
208
201
  expect(css).toContain('--h1-fs: clamp(28px,');
@@ -215,12 +208,10 @@ describe('cssGenerator', () => {
215
208
  test('breakpoints mode (default) keeps @media blocks for vars and DOES NOT emit --site-margin', () => {
216
209
  const css = generateVariablesCSS(
217
210
  {
218
- variables: [
219
- { name: 'h1-fs', cssVar: '--h1-fs', value: '32px', type: 'fontSize' },
220
- ],
211
+ variables: [{ name: 'h1-fs', cssVar: '--h1-fs', value: '32px', type: 'fontSize' }],
221
212
  },
222
213
  DEFAULT_BREAKPOINTS,
223
- { ...fluidScales, mode: 'breakpoints' }
214
+ { ...fluidScales, mode: 'breakpoints' },
224
215
  );
225
216
  expect(css).not.toContain('--site-margin');
226
217
  expect(css).toContain('@media (max-width: 1024px)');
@@ -6,7 +6,7 @@
6
6
 
7
7
  import type { ColorVariables, ThemeConfig } from '../shared/types/colors';
8
8
  import { resolvePaletteColor } from '../shared/types/colors';
9
- import type { VariablesConfig, CSSVariable } from '../shared/types/variables';
9
+ import type { VariablesConfig } from '../shared/types/variables';
10
10
  import type { BreakpointConfig } from '../shared/breakpoints';
11
11
  import type { ResponsiveScales, BreakpointScales } from '../shared/responsiveScaling';
12
12
  import {
@@ -80,11 +80,10 @@ export function generateThemeColorVariablesCSS(themeConfig: ThemeConfig): string
80
80
  export function generateVariablesCSS(
81
81
  config: VariablesConfig,
82
82
  breakpoints?: BreakpointConfig,
83
- responsiveScales?: ResponsiveScales
83
+ responsiveScales?: ResponsiveScales,
84
84
  ): string {
85
85
  const cssBlocks: string[] = [];
86
- const fluidActive =
87
- responsiveScales?.enabled === true && responsiveScales?.mode === 'fluid';
86
+ const fluidActive = responsiveScales?.enabled === true && responsiveScales?.mode === 'fluid';
88
87
 
89
88
  // Build base :root block: user-defined variables + (in fluid mode) --site-margin.
90
89
  // In fluid mode user variables get clamp() values directly on :root rather
@@ -93,18 +92,12 @@ export function generateVariablesCSS(
93
92
  const fluidBaseRef = responsiveScales?.baseReference || 16;
94
93
  const smallestBp = fluidActive ? getSmallestBreakpointName(breakpoints) : null;
95
94
 
96
- const baseVars: string[] = (config.variables ?? []).map(v => {
95
+ const baseVars: string[] = (config.variables ?? []).map((v) => {
97
96
  if (fluidActive && smallestBp && v.type !== 'none') {
98
97
  const categoryScales = responsiveScales?.[v.type] as BreakpointScales | undefined;
99
98
  const scale = categoryScales?.[smallestBp];
100
99
  if (scale != null && scale !== 1) {
101
- const fluid = buildFluidPropertyValue(
102
- v.value,
103
- scale,
104
- fluidRange.min,
105
- fluidRange.max,
106
- fluidBaseRef
107
- );
100
+ const fluid = buildFluidPropertyValue(v.value, scale, fluidRange.min, fluidRange.max, fluidBaseRef);
108
101
  if (fluid) return ` ${v.cssVar}: ${fluid};`;
109
102
  }
110
103
  }
@@ -129,15 +122,14 @@ export function generateVariablesCSS(
129
122
  const baseRef = responsiveScales.baseReference || 16;
130
123
 
131
124
  // Sort breakpoints by value descending (largest first)
132
- const sortedBreakpoints = Object.entries(breakpoints)
133
- .sort((a, b) => b[1].breakpoint - a[1].breakpoint);
125
+ const sortedBreakpoints = Object.entries(breakpoints).sort((a, b) => b[1].breakpoint - a[1].breakpoint);
134
126
 
135
127
  for (const [bpName, bpEntry] of sortedBreakpoints) {
136
128
  const scaledVars: string[] = [];
137
129
 
138
130
  for (const variable of userVariables) {
139
131
  // Per-variable override takes priority — stored string is the CSS value
140
- if (variable.scales && variable.scales[bpName]) {
132
+ if (variable.scales?.[bpName]) {
141
133
  const overrideValue = variable.scales[bpName];
142
134
  if (overrideValue !== variable.value) {
143
135
  scaledVars.push(` ${variable.cssVar}: ${overrideValue};`);
@@ -158,13 +150,10 @@ export function generateVariablesCSS(
158
150
  }
159
151
 
160
152
  if (scaledVars.length > 0) {
161
- cssBlocks.push(
162
- `@media (max-width: ${bpEntry.breakpoint}px) {\n :root {\n${scaledVars.join('\n')}\n }\n}`
163
- );
153
+ cssBlocks.push(`@media (max-width: ${bpEntry.breakpoint}px) {\n :root {\n${scaledVars.join('\n')}\n }\n}`);
164
154
  }
165
155
  }
166
156
  }
167
157
 
168
158
  return cssBlocks.join('\n');
169
159
  }
170
-