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
@@ -1,496 +1,498 @@
1
- import { test, expect, describe, beforeEach, afterEach, afterAll } from "bun:test";
1
+ import { test, expect, describe, afterEach } from 'bun:test';
2
2
 
3
3
  // Save original fetch before any test can modify it
4
4
  const _originalFetch = globalThis.fetch;
5
- import {
6
- resolveResponsiveStyleSync,
7
- resolveResponsiveStyle,
8
- initializeBreakpoints
9
- } from "./responsiveStyleResolver";
10
- import { getBreakpointName, DEFAULT_BREAKPOINTS } from "../shared/breakpoints";
11
- import type { ResponsiveStyleObject, StyleObject } from "../shared/types";
12
-
13
- describe("Responsive Style Resolver - getBreakpointName", () => {
14
- describe("Breakpoint detection", () => {
5
+ import { resolveResponsiveStyleSync, resolveResponsiveStyle, initializeBreakpoints } from './responsiveStyleResolver';
6
+ import { getBreakpointName, DEFAULT_BREAKPOINTS } from '../shared/breakpoints';
7
+ import type { ResponsiveStyleObject, StyleObject } from '../shared/types';
8
+
9
+ describe('Responsive Style Resolver - getBreakpointName', () => {
10
+ describe('Breakpoint detection', () => {
15
11
  test("should return 'base' for large viewport", () => {
16
12
  const viewportWidth = 1920;
17
13
  const result = getBreakpointName(viewportWidth);
18
- expect(result).toBe("base");
14
+ expect(result).toBe('base');
19
15
  });
20
16
 
21
17
  test("should return 'base' for viewport wider than tablet", () => {
22
18
  const viewportWidth = 1025;
23
19
  const result = getBreakpointName(viewportWidth);
24
- expect(result).toBe("base");
20
+ expect(result).toBe('base');
25
21
  });
26
22
 
27
23
  test("should return 'tablet' for viewport at tablet breakpoint", () => {
28
24
  const viewportWidth = 1024;
29
25
  const result = getBreakpointName(viewportWidth);
30
- expect(result).toBe("tablet");
26
+ expect(result).toBe('tablet');
31
27
  });
32
28
 
33
29
  test("should return 'tablet' for viewport between mobile and tablet", () => {
34
30
  const viewportWidth = 768;
35
31
  const result = getBreakpointName(viewportWidth);
36
- expect(result).toBe("tablet");
32
+ expect(result).toBe('tablet');
37
33
  });
38
34
 
39
35
  test("should return 'tablet' for viewport just above mobile breakpoint", () => {
40
36
  const viewportWidth = 541;
41
37
  const result = getBreakpointName(viewportWidth);
42
- expect(result).toBe("tablet");
38
+ expect(result).toBe('tablet');
43
39
  });
44
40
 
45
41
  test("should return 'mobile' for viewport at mobile breakpoint", () => {
46
42
  const viewportWidth = 540;
47
43
  const result = getBreakpointName(viewportWidth);
48
- expect(result).toBe("mobile");
44
+ expect(result).toBe('mobile');
49
45
  });
50
46
 
51
47
  test("should return 'mobile' for viewport smaller than mobile breakpoint", () => {
52
48
  const viewportWidth = 320;
53
49
  const result = getBreakpointName(viewportWidth);
54
- expect(result).toBe("mobile");
50
+ expect(result).toBe('mobile');
55
51
  });
56
52
 
57
- test("should use custom breakpoints when provided", () => {
53
+ test('should use custom breakpoints when provided', () => {
58
54
  const viewportWidth = 800;
59
55
  const customBreakpoints = {
60
56
  tablet: { breakpoint: 900, previewPoint: 768 },
61
- mobile: { breakpoint: 400, previewPoint: 375 }
57
+ mobile: { breakpoint: 400, previewPoint: 375 },
62
58
  };
63
59
  const result = getBreakpointName(viewportWidth, customBreakpoints);
64
- expect(result).toBe("tablet");
60
+ expect(result).toBe('tablet');
65
61
  });
66
62
  });
67
63
 
68
- describe("Edge cases", () => {
69
- test("should handle exact breakpoint boundaries", () => {
70
- const tabletWidth = DEFAULT_BREAKPOINTS.tablet.breakpoint;
71
- const mobileWidth = DEFAULT_BREAKPOINTS.mobile.breakpoint;
64
+ describe('Edge cases', () => {
65
+ test('should handle exact breakpoint boundaries', () => {
66
+ const tabletWidth = DEFAULT_BREAKPOINTS.tablet!.breakpoint;
67
+ const mobileWidth = DEFAULT_BREAKPOINTS.mobile!.breakpoint;
72
68
 
73
- expect(getBreakpointName(tabletWidth)).toBe("tablet");
74
- expect(getBreakpointName(tabletWidth - 1)).toBe("tablet");
75
- expect(getBreakpointName(tabletWidth + 1)).toBe("base");
69
+ expect(getBreakpointName(tabletWidth)).toBe('tablet');
70
+ expect(getBreakpointName(tabletWidth - 1)).toBe('tablet');
71
+ expect(getBreakpointName(tabletWidth + 1)).toBe('base');
76
72
 
77
- expect(getBreakpointName(mobileWidth)).toBe("mobile");
78
- expect(getBreakpointName(mobileWidth - 1)).toBe("mobile");
79
- expect(getBreakpointName(mobileWidth + 1)).toBe("tablet");
73
+ expect(getBreakpointName(mobileWidth)).toBe('mobile');
74
+ expect(getBreakpointName(mobileWidth - 1)).toBe('mobile');
75
+ expect(getBreakpointName(mobileWidth + 1)).toBe('tablet');
80
76
  });
81
77
 
82
- test("should handle zero viewport width", () => {
78
+ test('should handle zero viewport width', () => {
83
79
  const result = getBreakpointName(0);
84
- expect(result).toBe("mobile");
80
+ expect(result).toBe('mobile');
85
81
  });
86
82
 
87
- test("should handle very large viewport width", () => {
83
+ test('should handle very large viewport width', () => {
88
84
  const result = getBreakpointName(10000);
89
- expect(result).toBe("base");
85
+ expect(result).toBe('base');
90
86
  });
91
87
  });
92
88
  });
93
89
 
94
- describe("Responsive Style Resolver - resolveResponsiveStyleSync", () => {
95
- describe("Non-responsive styles", () => {
96
- test("should pass through flat style objects", () => {
90
+ describe('Responsive Style Resolver - resolveResponsiveStyleSync', () => {
91
+ describe('Non-responsive styles', () => {
92
+ test('should pass through flat style objects', () => {
97
93
  const style: StyleObject = {
98
- color: "red",
99
- fontSize: "16px"
94
+ color: 'red',
95
+ fontSize: '16px',
100
96
  };
101
-
97
+
102
98
  const result = resolveResponsiveStyleSync(style);
103
99
  expect(result).toEqual(style);
104
- expect(result.color).toBe("red");
105
- expect(result.fontSize).toBe("16px");
100
+ expect(result.color).toBe('red');
101
+ expect(result.fontSize).toBe('16px');
106
102
  });
107
103
 
108
- test("should return same object for non-responsive styles", () => {
104
+ test('should return same object for non-responsive styles', () => {
109
105
  const style: StyleObject = {
110
- padding: "10px",
111
- margin: "20px"
106
+ padding: '10px',
107
+ margin: '20px',
112
108
  };
113
-
109
+
114
110
  const result = resolveResponsiveStyleSync(style);
115
111
  expect(result).toBe(style); // Should return same reference for flat styles
116
112
  });
117
113
  });
118
114
 
119
- describe("Responsive styles - viewport strategy", () => {
120
- test("should merge base only styles at base breakpoint", () => {
115
+ describe('Responsive styles - viewport strategy', () => {
116
+ test('should merge base only styles at base breakpoint', () => {
121
117
  const style: ResponsiveStyleObject = {
122
118
  base: {
123
- color: "red",
124
- fontSize: "16px"
125
- }
119
+ color: 'red',
120
+ fontSize: '16px',
121
+ },
126
122
  };
127
123
  const viewportWidth = 1920;
128
-
124
+
129
125
  const result = resolveResponsiveStyleSync(style, viewportWidth);
130
-
131
- expect(result.color).toBe("red");
132
- expect(result.fontSize).toBe("16px");
126
+
127
+ expect(result.color).toBe('red');
128
+ expect(result.fontSize).toBe('16px');
133
129
  });
134
130
 
135
- test("should merge base and tablet styles at tablet breakpoint", () => {
131
+ test('should merge base and tablet styles at tablet breakpoint', () => {
136
132
  const style: ResponsiveStyleObject = {
137
133
  base: {
138
- color: "red",
139
- fontSize: "16px"
134
+ color: 'red',
135
+ fontSize: '16px',
140
136
  },
141
137
  tablet: {
142
- fontSize: "14px",
143
- padding: "10px"
144
- }
138
+ fontSize: '14px',
139
+ padding: '10px',
140
+ },
145
141
  };
146
142
  const viewportWidth = 768;
147
-
143
+
148
144
  const result = resolveResponsiveStyleSync(style, viewportWidth);
149
-
150
- expect(result.color).toBe("red"); // From base
151
- expect(result.fontSize).toBe("14px"); // Overridden by tablet
152
- expect(result.padding).toBe("10px"); // From tablet
145
+
146
+ expect(result.color).toBe('red'); // From base
147
+ expect(result.fontSize).toBe('14px'); // Overridden by tablet
148
+ expect(result.padding).toBe('10px'); // From tablet
153
149
  });
154
150
 
155
- test("should merge all breakpoints at mobile breakpoint", () => {
151
+ test('should merge all breakpoints at mobile breakpoint', () => {
156
152
  const style: ResponsiveStyleObject = {
157
153
  base: {
158
- color: "red",
159
- fontSize: "16px"
154
+ color: 'red',
155
+ fontSize: '16px',
160
156
  },
161
157
  tablet: {
162
- fontSize: "14px"
158
+ fontSize: '14px',
163
159
  },
164
160
  mobile: {
165
- fontSize: "12px",
166
- color: "blue"
167
- }
161
+ fontSize: '12px',
162
+ color: 'blue',
163
+ },
168
164
  };
169
165
  const viewportWidth = 320;
170
-
166
+
171
167
  const result = resolveResponsiveStyleSync(style, viewportWidth);
172
-
173
- expect(result.color).toBe("blue"); // Overridden by mobile
174
- expect(result.fontSize).toBe("12px"); // Overridden by mobile
168
+
169
+ expect(result.color).toBe('blue'); // Overridden by mobile
170
+ expect(result.fontSize).toBe('12px'); // Overridden by mobile
175
171
  });
176
172
 
177
- test("should apply tablet styles at tablet viewport", () => {
173
+ test('should apply tablet styles at tablet viewport', () => {
178
174
  const style: ResponsiveStyleObject = {
179
175
  base: {
180
- padding: "20px"
176
+ padding: '20px',
181
177
  },
182
178
  tablet: {
183
- padding: "15px"
184
- }
179
+ padding: '15px',
180
+ },
185
181
  };
186
182
  const viewportWidth = 1024;
187
-
183
+
188
184
  const result = resolveResponsiveStyleSync(style, viewportWidth);
189
-
190
- expect(result.padding).toBe("15px");
185
+
186
+ expect(result.padding).toBe('15px');
191
187
  });
192
188
 
193
- test("should apply mobile styles at mobile viewport", () => {
189
+ test('should apply mobile styles at mobile viewport', () => {
194
190
  const style: ResponsiveStyleObject = {
195
191
  base: {
196
- padding: "20px"
192
+ padding: '20px',
197
193
  },
198
194
  tablet: {
199
- padding: "15px"
195
+ padding: '15px',
200
196
  },
201
197
  mobile: {
202
- padding: "10px"
203
- }
198
+ padding: '10px',
199
+ },
204
200
  };
205
201
  const viewportWidth = 540;
206
-
202
+
207
203
  const result = resolveResponsiveStyleSync(style, viewportWidth);
208
-
209
- expect(result.padding).toBe("10px");
204
+
205
+ expect(result.padding).toBe('10px');
210
206
  });
211
207
  });
212
208
 
213
- describe("Responsive styles - style object variations", () => {
214
- test("should handle styles with base only", () => {
209
+ describe('Responsive styles - style object variations', () => {
210
+ test('should handle styles with base only', () => {
215
211
  const style: ResponsiveStyleObject = {
216
212
  base: {
217
- color: "black",
218
- backgroundColor: "white"
219
- }
213
+ color: 'black',
214
+ backgroundColor: 'white',
215
+ },
220
216
  };
221
-
217
+
222
218
  const result = resolveResponsiveStyleSync(style, 1920);
223
-
224
- expect(result.color).toBe("black");
225
- expect(result.backgroundColor).toBe("white");
219
+
220
+ expect(result.color).toBe('black');
221
+ expect(result.backgroundColor).toBe('white');
226
222
  });
227
223
 
228
- test("should handle styles with base and tablet", () => {
224
+ test('should handle styles with base and tablet', () => {
229
225
  const style: ResponsiveStyleObject = {
230
226
  base: {
231
- fontSize: "16px"
227
+ fontSize: '16px',
232
228
  },
233
229
  tablet: {
234
- fontSize: "14px"
235
- }
230
+ fontSize: '14px',
231
+ },
236
232
  };
237
-
233
+
238
234
  const result = resolveResponsiveStyleSync(style, 768);
239
-
240
- expect(result.fontSize).toBe("14px");
235
+
236
+ expect(result.fontSize).toBe('14px');
241
237
  });
242
238
 
243
- test("should handle styles with all breakpoints", () => {
239
+ test('should handle styles with all breakpoints', () => {
244
240
  const style: ResponsiveStyleObject = {
245
241
  base: {
246
- fontSize: "18px",
247
- color: "black"
242
+ fontSize: '18px',
243
+ color: 'black',
248
244
  },
249
245
  tablet: {
250
- fontSize: "16px"
246
+ fontSize: '16px',
251
247
  },
252
248
  mobile: {
253
- fontSize: "14px",
254
- color: "gray"
255
- }
249
+ fontSize: '14px',
250
+ color: 'gray',
251
+ },
256
252
  };
257
-
253
+
258
254
  const result = resolveResponsiveStyleSync(style, 320);
259
-
260
- expect(result.fontSize).toBe("14px");
261
- expect(result.color).toBe("gray");
255
+
256
+ expect(result.fontSize).toBe('14px');
257
+ expect(result.color).toBe('gray');
262
258
  });
263
259
 
264
- test("should handle missing breakpoint styles", () => {
260
+ test('should handle missing breakpoint styles', () => {
265
261
  const style: ResponsiveStyleObject = {
266
262
  base: {
267
- color: "red"
268
- }
263
+ color: 'red',
264
+ },
269
265
  // No tablet or mobile
270
266
  };
271
-
267
+
272
268
  const result = resolveResponsiveStyleSync(style, 320);
273
-
274
- expect(result.color).toBe("red"); // Should still have base styles
269
+
270
+ expect(result.color).toBe('red'); // Should still have base styles
275
271
  });
276
272
 
277
- test("should handle empty base styles", () => {
273
+ test('should handle empty base styles', () => {
278
274
  const style: ResponsiveStyleObject = {
279
275
  base: {},
280
276
  tablet: {
281
- fontSize: "14px"
282
- }
277
+ fontSize: '14px',
278
+ },
283
279
  };
284
-
280
+
285
281
  const result = resolveResponsiveStyleSync(style, 768);
286
-
287
- expect(result.fontSize).toBe("14px");
282
+
283
+ expect(result.fontSize).toBe('14px');
288
284
  });
289
285
  });
290
286
 
291
- describe("Edge cases", () => {
292
- test("should handle empty responsive style object", () => {
287
+ describe('Edge cases', () => {
288
+ test('should handle empty responsive style object', () => {
293
289
  const style: ResponsiveStyleObject = {
294
- base: {}
290
+ base: {},
295
291
  };
296
-
292
+
297
293
  const result = resolveResponsiveStyleSync(style, 1920);
298
-
294
+
299
295
  expect(Object.keys(result).length).toBe(0);
300
296
  });
301
297
 
302
- test("should handle viewport width at exact tablet boundary", () => {
298
+ test('should handle viewport width at exact tablet boundary', () => {
303
299
  const style: ResponsiveStyleObject = {
304
- base: { fontSize: "16px" },
305
- tablet: { fontSize: "14px" }
300
+ base: { fontSize: '16px' },
301
+ tablet: { fontSize: '14px' },
306
302
  };
307
303
 
308
- const result = resolveResponsiveStyleSync(style, DEFAULT_BREAKPOINTS.tablet.breakpoint);
304
+ const result = resolveResponsiveStyleSync(style, DEFAULT_BREAKPOINTS.tablet!.breakpoint);
309
305
 
310
- expect(result.fontSize).toBe("14px");
306
+ expect(result.fontSize).toBe('14px');
311
307
  });
312
308
 
313
- test("should handle viewport width at exact mobile boundary", () => {
309
+ test('should handle viewport width at exact mobile boundary', () => {
314
310
  const style: ResponsiveStyleObject = {
315
- base: { fontSize: "16px" },
316
- tablet: { fontSize: "14px" },
317
- mobile: { fontSize: "12px" }
311
+ base: { fontSize: '16px' },
312
+ tablet: { fontSize: '14px' },
313
+ mobile: { fontSize: '12px' },
318
314
  };
319
315
 
320
- const result = resolveResponsiveStyleSync(style, DEFAULT_BREAKPOINTS.mobile.breakpoint);
316
+ const result = resolveResponsiveStyleSync(style, DEFAULT_BREAKPOINTS.mobile!.breakpoint);
321
317
 
322
- expect(result.fontSize).toBe("12px");
318
+ expect(result.fontSize).toBe('12px');
323
319
  });
324
320
 
325
- test("should use default viewport width when not provided", () => {
321
+ test('should use default viewport width when not provided', () => {
326
322
  const style: ResponsiveStyleObject = {
327
- base: { fontSize: "16px" }
323
+ base: { fontSize: '16px' },
328
324
  };
329
-
325
+
330
326
  // Should use window.innerWidth or 1920 as default
331
327
  const result = resolveResponsiveStyleSync(style);
332
-
333
- expect(result.fontSize).toBe("16px");
328
+
329
+ expect(result.fontSize).toBe('16px');
334
330
  // Note: Can't reliably test the exact default without window object in test env
335
331
  });
336
332
  });
337
333
  });
338
334
 
339
- describe("Responsive Style Resolver - resolveResponsiveStyle (async)", () => {
335
+ describe('Responsive Style Resolver - resolveResponsiveStyle (async)', () => {
340
336
  afterEach(() => {
341
337
  globalThis.fetch = _originalFetch;
342
338
  });
343
339
 
344
- test("should resolve non-responsive styles asynchronously", async () => {
340
+ test('should resolve non-responsive styles asynchronously', async () => {
345
341
  const style: StyleObject = {
346
- color: "red"
342
+ color: 'red',
347
343
  };
348
-
344
+
349
345
  const result = await resolveResponsiveStyle(style);
350
-
346
+
351
347
  expect(result).toEqual(style);
352
348
  });
353
349
 
354
- test("should resolve responsive styles with default breakpoints on fetch error", async () => {
350
+ test('should resolve responsive styles with default breakpoints on fetch error', async () => {
355
351
  // Mock fetch to fail
356
352
  globalThis.fetch = (() => Promise.reject(new Error('Network error'))) as unknown as typeof fetch;
357
-
353
+
358
354
  const style: ResponsiveStyleObject = {
359
355
  base: {
360
- fontSize: "16px"
356
+ fontSize: '16px',
361
357
  },
362
358
  tablet: {
363
- fontSize: "14px"
364
- }
359
+ fontSize: '14px',
360
+ },
365
361
  };
366
-
362
+
367
363
  const result = await resolveResponsiveStyle(style);
368
-
364
+
369
365
  // Should use default breakpoints and resolve based on window.innerWidth or 1920
370
366
  expect(result.fontSize).toBeDefined();
371
367
  });
372
368
 
373
- test("should handle async breakpoint config loading", async () => {
369
+ test('should handle async breakpoint config loading', async () => {
374
370
  // Mock successful fetch
375
- globalThis.fetch = (() => Promise.resolve({
376
- json: () => Promise.resolve({
377
- breakpoints: {
378
- tablet: 900,
379
- mobile: 400
380
- }
381
- })
382
- })) as unknown as typeof fetch;
383
-
371
+ globalThis.fetch = (() =>
372
+ Promise.resolve({
373
+ json: () =>
374
+ Promise.resolve({
375
+ breakpoints: {
376
+ tablet: 900,
377
+ mobile: 400,
378
+ },
379
+ }),
380
+ })) as unknown as typeof fetch;
381
+
384
382
  const style: ResponsiveStyleObject = {
385
- base: { fontSize: "16px" },
386
- tablet: { fontSize: "14px" }
383
+ base: { fontSize: '16px' },
384
+ tablet: { fontSize: '14px' },
387
385
  };
388
-
386
+
389
387
  // First call should trigger config load
390
388
  await resolveResponsiveStyle(style);
391
-
389
+
392
390
  // Second call should use cached config
393
391
  const result = await resolveResponsiveStyle(style);
394
-
392
+
395
393
  expect(result.fontSize).toBeDefined();
396
394
  });
397
395
  });
398
396
 
399
- describe("Responsive Style Resolver - initializeBreakpoints", () => {
397
+ describe('Responsive Style Resolver - initializeBreakpoints', () => {
400
398
  afterEach(() => {
401
399
  globalThis.fetch = _originalFetch;
402
400
  });
403
401
 
404
- test("should initialize breakpoint config", async () => {
402
+ test('should initialize breakpoint config', async () => {
405
403
  // Mock successful fetch
406
- globalThis.fetch = (() => Promise.resolve({
407
- json: () => Promise.resolve({
408
- breakpoints: {
409
- tablet: 900,
410
- mobile: 400
411
- }
412
- })
413
- })) as unknown as typeof fetch;
414
-
404
+ globalThis.fetch = (() =>
405
+ Promise.resolve({
406
+ json: () =>
407
+ Promise.resolve({
408
+ breakpoints: {
409
+ tablet: 900,
410
+ mobile: 400,
411
+ },
412
+ }),
413
+ })) as unknown as typeof fetch;
414
+
415
415
  await initializeBreakpoints();
416
-
416
+
417
417
  // If initialization succeeds, subsequent resolveResponsiveStyleSync should use cached config
418
418
  const style: ResponsiveStyleObject = {
419
- base: { fontSize: "16px" }
419
+ base: { fontSize: '16px' },
420
420
  };
421
-
421
+
422
422
  const result = resolveResponsiveStyleSync(style);
423
- expect(result.fontSize).toBe("16px");
423
+ expect(result.fontSize).toBe('16px');
424
424
  });
425
425
 
426
- test("should handle initialization error gracefully", async () => {
426
+ test('should handle initialization error gracefully', async () => {
427
427
  // Mock fetch to fail
428
428
  globalThis.fetch = (() => Promise.reject(new Error('Network error'))) as unknown as typeof fetch;
429
-
429
+
430
430
  // Should not throw
431
431
  await expect(initializeBreakpoints()).resolves.toBeUndefined();
432
432
  });
433
433
  });
434
434
 
435
- describe("Responsive Style Resolver - Real-world examples", () => {
436
- test("should handle complex responsive style from index.json example", () => {
435
+ describe('Responsive Style Resolver - Real-world examples', () => {
436
+ test('should handle complex responsive style from index.json example', () => {
437
437
  // Based on pages/index.json - h1 with responsive fontSize
438
438
  const style: ResponsiveStyleObject = {
439
439
  base: {
440
- fontSize: "89px",
441
- fontWeight: "600",
442
- marginBottom: "16px",
443
- color: "#1f2937",
444
- letterSpacing: "-0.02em"
440
+ fontSize: '89px',
441
+ fontWeight: '600',
442
+ marginBottom: '16px',
443
+ color: '#1f2937',
444
+ letterSpacing: '-0.02em',
445
445
  },
446
446
  tablet: {
447
- fontSize: "32px"
447
+ fontSize: '32px',
448
448
  },
449
- mobile: {}
449
+ mobile: {},
450
450
  };
451
-
451
+
452
452
  // Test at base viewport
453
453
  const resultBase = resolveResponsiveStyleSync(style, 1920);
454
- expect(resultBase.fontSize).toBe("89px");
455
- expect(resultBase.fontWeight).toBe("600");
456
-
454
+ expect(resultBase.fontSize).toBe('89px');
455
+ expect(resultBase.fontWeight).toBe('600');
456
+
457
457
  // Test at tablet viewport
458
458
  const resultTablet = resolveResponsiveStyleSync(style, 768);
459
- expect(resultTablet.fontSize).toBe("32px");
460
- expect(resultTablet.fontWeight).toBe("600"); // From base
461
-
459
+ expect(resultTablet.fontSize).toBe('32px');
460
+ expect(resultTablet.fontWeight).toBe('600'); // From base
461
+
462
462
  // Test at mobile viewport
463
- // Implementation note: viewport strategy applies base + active breakpoint only
464
- // Tablet styles don't cascade to mobile - each breakpoint is independent
463
+ // Implementation note: viewport strategy mirrors the CSS max-width cascade
464
+ // every breakpoint whose range includes the viewport applies, larger first.
465
+ // At 320px both tablet and mobile ranges include the viewport, so tablet's
466
+ // fontSize applies (mobile is empty and overrides nothing).
465
467
  const resultMobile = resolveResponsiveStyleSync(style, 320);
466
- expect(resultMobile.fontSize).toBe("89px"); // Base only (mobile is empty, tablet doesn't cascade)
467
- expect(resultMobile.fontWeight).toBe("600"); // From base
468
+ expect(resultMobile.fontSize).toBe('32px'); // Tablet cascades to mobile (CSS max-width semantics)
469
+ expect(resultMobile.fontWeight).toBe('600'); // From base
468
470
  });
469
471
 
470
- test("should apply base + active breakpoint styles", () => {
471
- // Implementation note: viewport strategy applies base + active breakpoint only
472
- // Tablet styles don't cascade to mobile - each breakpoint is independent
472
+ test('should apply base + cascading breakpoint styles', () => {
473
+ // Implementation note: viewport strategy mirrors the CSS max-width cascade
474
+ // at a mobile viewport, tablet styles apply first, then mobile overrides.
473
475
  const style: ResponsiveStyleObject = {
474
476
  base: {
475
- padding: "20px",
476
- margin: "10px",
477
- color: "black"
477
+ padding: '20px',
478
+ margin: '10px',
479
+ color: 'black',
478
480
  },
479
481
  tablet: {
480
- padding: "15px",
481
- fontSize: "14px"
482
+ padding: '15px',
483
+ fontSize: '14px',
482
484
  },
483
485
  mobile: {
484
- padding: "10px",
485
- color: "gray"
486
- }
486
+ padding: '10px',
487
+ color: 'gray',
488
+ },
487
489
  };
488
490
 
489
491
  const result = resolveResponsiveStyleSync(style, 320);
490
492
 
491
- expect(result.padding).toBe("10px"); // Mobile overrides
492
- expect(result.margin).toBe("10px"); // From base
493
- expect(result.color).toBe("gray"); // Mobile overrides
494
- expect(result.fontSize).toBeUndefined(); // Tablet doesn't cascade to mobile
493
+ expect(result.padding).toBe('10px'); // Mobile overrides tablet's 15px
494
+ expect(result.margin).toBe('10px'); // From base
495
+ expect(result.color).toBe('gray'); // Mobile overrides
496
+ expect(result.fontSize).toBe('14px'); // Tablet cascades to mobile (CSS max-width semantics)
495
497
  });
496
498
  });