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,9 +1,9 @@
1
1
  /**
2
2
  * Router Component
3
- *
3
+ *
4
4
  * Main router component that handles routing, state management, and rendering.
5
5
  * Uses all extracted modules for a clean, modular architecture.
6
- *
6
+ *
7
7
  * Responsibilities:
8
8
  * - Route loading and navigation
9
9
  * - Component tree state management
@@ -13,24 +13,24 @@
13
13
  * - Viewport width tracking for responsive styles
14
14
  */
15
15
 
16
- import { createElement as h, useState, useEffect, useLayoutEffect, useRef, useCallback, useMemo } from "react";
17
- import type { ReactElement } from "react";
18
- import { renderPage } from "../core/ComponentRenderer";
19
- import { RouteLoader } from "./RouteLoader";
20
- import { detectSSRContent, getInitialLoadingState } from "../hydration/HydrationUtils";
21
- import { HMRManager } from "../hmr/HMRManager";
22
- import { createNavigationHandler } from "../navigation";
23
- import { initializeBreakpoints } from "../responsiveStyleResolver";
24
- import { elementRegistry } from "../elementRegistry";
25
- import { InteractiveStylesRegistry } from "../InteractiveStylesRegistry";
26
- import { UtilityClassCollector } from "../styles/UtilityClassCollector";
27
- import { applyNonce } from "../styles/cspNonce";
28
- import { initializeClient, setupEventHandlers } from "../ClientInitializer";
29
- import type { ComponentNode, I18nConfig, PrefetchConfig, CMSItem } from "../../shared/types";
30
- import { parseLocaleFromPath, setStoredLocale, DEFAULT_I18N_CONFIG } from "../../shared/i18n";
31
- import { fetchI18nConfig, setI18nConfig as setCachedI18nConfig } from "../i18nConfigService";
32
- import { IFRAME_MESSAGE_TYPES } from "../../shared/constants";
33
- import { rewriteViewportUnits } from "../../shared/viewportUnits";
16
+ import { createElement as h, useState, useEffect, useLayoutEffect, useRef, useCallback, useMemo } from 'react';
17
+ import type { ReactElement } from 'react';
18
+ import { renderPage } from '../core/ComponentRenderer';
19
+ import { RouteLoader } from './RouteLoader';
20
+ import { detectSSRContent, getInitialLoadingState } from '../hydration/HydrationUtils';
21
+ import { HMRManager } from '../hmr/HMRManager';
22
+ import { createNavigationHandler } from '../navigation';
23
+ import { initializeBreakpoints } from '../responsiveStyleResolver';
24
+ import { elementRegistry } from '../elementRegistry';
25
+ import { InteractiveStylesRegistry } from '../InteractiveStylesRegistry';
26
+ import { UtilityClassCollector } from '../styles/UtilityClassCollector';
27
+ import { applyNonce } from '../styles/cspNonce';
28
+ import { initializeClient, setupEventHandlers } from '../ClientInitializer';
29
+ import type { ComponentNode, I18nConfig, PrefetchConfig, CMSItem } from '../../shared/types';
30
+ import { parseLocaleFromPath, setStoredLocale, DEFAULT_I18N_CONFIG } from '../../shared/i18n';
31
+ import { fetchI18nConfig, setI18nConfig as setCachedI18nConfig, invalidateI18nConfig } from '../i18nConfigService';
32
+ import { IFRAME_MESSAGE_TYPES } from '../../shared/constants';
33
+ import { rewriteViewportUnits } from '../../shared/viewportUnits';
34
34
 
35
35
  /** SSR-serialized CMS context for client-side hydration */
36
36
  interface SSRCMSContext {
@@ -79,10 +79,10 @@ export interface RouterProps {
79
79
 
80
80
  /**
81
81
  * Router Component
82
- *
82
+ *
83
83
  * Main router component that handles client-side routing, page loading, and rendering.
84
84
  * Manages component tree state, loading states, and integrates with HMR for hot reloading.
85
- *
85
+ *
86
86
  * Features:
87
87
  * - Automatic route loading on path changes
88
88
  * - SSR hydration support
@@ -90,15 +90,15 @@ export interface RouterProps {
90
90
  * - 404 handling with available pages list
91
91
  * - Viewport width tracking for responsive styles
92
92
  * - HMR integration for development
93
- *
93
+ *
94
94
  * @param props - Router configuration props
95
95
  * @returns ReactElement representing the router and current page
96
- *
96
+ *
97
97
  * @example
98
98
  * ```tsx
99
99
  * // Basic usage
100
100
  * <Router />
101
- *
101
+ *
102
102
  * // With custom initial path
103
103
  * <Router initialPath="/custom" />
104
104
  * ```
@@ -113,11 +113,11 @@ export function Router(props: RouterProps = {}): ReactElement {
113
113
  // Setup event handlers on mount
114
114
  useEffect(() => {
115
115
  const cleanup = setupEventHandlers(services);
116
-
116
+
117
117
  // Cleanup on unmount
118
118
  return cleanup;
119
119
  }, [services]);
120
-
120
+
121
121
  // State management
122
122
  const [componentTree, setComponentTree] = useState<ComponentNode | ComponentNode[] | null>(null);
123
123
  // Keep previous componentTree to show during transitions
@@ -130,16 +130,14 @@ export function Router(props: RouterProps = {}): ReactElement {
130
130
  const [currentPath, setCurrentPath] = useState(initialPath);
131
131
  const [availablePages, setAvailablePages] = useState<string[]>([]);
132
132
  const [showNotFound, setShowNotFound] = useState(false);
133
- const [viewportWidth, setViewportWidth] = useState<number>(
134
- typeof window !== 'undefined' ? window.innerWidth : 1920
135
- );
133
+ const [viewportWidth, setViewportWidth] = useState<number>(typeof window !== 'undefined' ? window.innerWidth : 1920);
136
134
  const [i18nConfig, setI18nConfig] = useState<I18nConfig>(DEFAULT_I18N_CONFIG);
137
135
  const [currentLocale, setCurrentLocale] = useState<string>(DEFAULT_I18N_CONFIG.defaultLocale);
138
136
  const [cmsContext, setCmsContext] = useState<Record<string, unknown> | null>(null);
139
137
  const [cmsLocale, setCmsLocale] = useState<string | null>(null);
140
138
  const [registryVersion, setRegistryVersion] = useState(0);
141
139
  // Don't block rendering waiting for CMS context - render immediately and re-render when context arrives
142
- const [awaitingCmsContext, setAwaitingCmsContext] = useState(false);
140
+ const [awaitingCmsContext, _setAwaitingCmsContext] = useState(false);
143
141
  const [collectionItemsMap, setCollectionItemsMap] = useState<Record<string, CMSItem[]>>({});
144
142
  // Store CMS template path for HMR reloads (so we don't lose it after initial load)
145
143
  const [cmsTemplatePath, setCmsTemplatePath] = useState<string | null>(null);
@@ -161,36 +159,38 @@ export function Router(props: RouterProps = {}): ReactElement {
161
159
  const initialLoadDoneRef = useRef(false);
162
160
 
163
161
  // Create RouteLoader instance
164
- const routeLoader = useRef(new RouteLoader({
165
- componentRegistry: services.componentRegistry,
166
- prefetchService: services.prefetchService,
167
- onLoadStart: () => {
168
- setLoading(true);
169
- setShowNotFound(false);
170
- // Clear interactive styles and utility class registries before new render
171
- InteractiveStylesRegistry.clear();
172
- UtilityClassCollector.clear();
173
- // Save current componentTree as previous before loading
174
- if (componentTreeRef.current) {
175
- setPreviousComponentTree(componentTreeRef.current);
176
- }
177
- },
178
- onLoadComplete: (tree) => {
179
- setComponentTree(tree);
180
- setLoading(false);
181
- setShowNotFound(false);
182
- // Clear previous componentTree now that we have new content
183
- setPreviousComponentTree(null);
184
- },
185
- onLoadError: (error) => {
186
- setLoading(false);
187
- setShowNotFound(false);
188
- setPreviousComponentTree(null);
189
- },
190
- onNotFound: () => setShowNotFound(true),
191
- onPagesLoaded: (pages) => setAvailablePages(pages),
192
- onLocaleDetected: (locale) => setCurrentLocale(locale),
193
- })).current;
162
+ const routeLoader = useRef(
163
+ new RouteLoader({
164
+ componentRegistry: services.componentRegistry,
165
+ prefetchService: services.prefetchService,
166
+ onLoadStart: () => {
167
+ setLoading(true);
168
+ setShowNotFound(false);
169
+ // Clear interactive styles and utility class registries before new render
170
+ InteractiveStylesRegistry.clear();
171
+ UtilityClassCollector.clear();
172
+ // Save current componentTree as previous before loading
173
+ if (componentTreeRef.current) {
174
+ setPreviousComponentTree(componentTreeRef.current);
175
+ }
176
+ },
177
+ onLoadComplete: (tree) => {
178
+ setComponentTree(tree);
179
+ setLoading(false);
180
+ setShowNotFound(false);
181
+ // Clear previous componentTree now that we have new content
182
+ setPreviousComponentTree(null);
183
+ },
184
+ onLoadError: (_error) => {
185
+ setLoading(false);
186
+ setShowNotFound(false);
187
+ setPreviousComponentTree(null);
188
+ },
189
+ onNotFound: () => setShowNotFound(true),
190
+ onPagesLoaded: (pages) => setAvailablePages(pages),
191
+ onLocaleDetected: (locale) => setCurrentLocale(locale),
192
+ }),
193
+ ).current;
194
194
 
195
195
  // Keep ref in sync with state
196
196
  useEffect(() => {
@@ -204,7 +204,7 @@ export function Router(props: RouterProps = {}): ReactElement {
204
204
 
205
205
  // Load i18n config on mount using shared service
206
206
  useEffect(() => {
207
- fetchI18nConfig().then(config => {
207
+ fetchI18nConfig().then((config) => {
208
208
  setI18nConfig(config);
209
209
  setCachedI18nConfig(config);
210
210
  // Update RouteLoader with i18n config so it can extract locale from paths
@@ -216,6 +216,28 @@ export function Router(props: RouterProps = {}): ReactElement {
216
216
  });
217
217
  }, []);
218
218
 
219
+ // Refresh the i18n config when project.config.json changes on disk (the HMRManager
220
+ // dispatches `hmr-config-update` for the server's `hmr:config-update` broadcast).
221
+ // Without this, adding a locale in the editor leaves this canvas with the stale
222
+ // locale set: the new locale's paths (e.g. /pl) don't parse as locale-prefixed,
223
+ // the literal path misses every page, and the canvas shows "Page not found" until
224
+ // a full reload. After the refetch, re-resolve the current route so an already
225
+ // failed (or locale-dependent) view recovers in place.
226
+ useEffect(() => {
227
+ const handleConfigUpdate = () => {
228
+ invalidateI18nConfig();
229
+ fetchI18nConfig().then((config) => {
230
+ setI18nConfig(config);
231
+ setCachedI18nConfig(config);
232
+ routeLoader.setI18nConfig(config);
233
+ setShowNotFound(false);
234
+ loadComponentsRef.current(window.location.pathname);
235
+ });
236
+ };
237
+ document.addEventListener('hmr-config-update', handleConfigUpdate);
238
+ return () => document.removeEventListener('hmr-config-update', handleConfigUpdate);
239
+ }, []);
240
+
219
241
  // Update locale when path changes
220
242
  useEffect(() => {
221
243
  const { locale } = parseLocaleFromPath(currentPath, i18nConfig);
@@ -274,8 +296,10 @@ export function Router(props: RouterProps = {}): ReactElement {
274
296
  // non-base → max-width of that breakpoint). When `media` is omitted (no
275
297
  // breakpoints configured) the rule applies unconditionally. The legacy
276
298
  // {maxWidth} payload from CSS_VARIABLE_SCOPED_UPDATE is still accepted.
277
- if (event.data?.type === IFRAME_MESSAGE_TYPES.CSS_VARIABLE_UPDATE
278
- || event.data?.type === IFRAME_MESSAGE_TYPES.CSS_VARIABLE_SCOPED_UPDATE) {
299
+ if (
300
+ event.data?.type === IFRAME_MESSAGE_TYPES.CSS_VARIABLE_UPDATE ||
301
+ event.data?.type === IFRAME_MESSAGE_TYPES.CSS_VARIABLE_SCOPED_UPDATE
302
+ ) {
279
303
  const { name, value, media, maxWidth } = event.data as {
280
304
  name: string;
281
305
  value: string;
@@ -374,7 +398,7 @@ export function Router(props: RouterProps = {}): ReactElement {
374
398
  const { componentName, definition } = event.data;
375
399
  if (componentName && definition) {
376
400
  services.componentRegistry.register(componentName, definition);
377
- setRegistryVersion(v => v + 1);
401
+ setRegistryVersion((v) => v + 1);
378
402
  }
379
403
  }
380
404
  };
@@ -389,9 +413,12 @@ export function Router(props: RouterProps = {}): ReactElement {
389
413
  if (typeof window === 'undefined') return;
390
414
  if (window.parent === window) return; // Not in iframe
391
415
 
392
- window.parent.postMessage({
393
- type: IFRAME_MESSAGE_TYPES.CMS_CONTEXT_REQUEST
394
- }, '*');
416
+ window.parent.postMessage(
417
+ {
418
+ type: IFRAME_MESSAGE_TYPES.CMS_CONTEXT_REQUEST,
419
+ },
420
+ '*',
421
+ );
395
422
  }, []);
396
423
 
397
424
  // Inject CSS before browser paint to prevent FOUC on client-side navigation
@@ -414,10 +441,13 @@ export function Router(props: RouterProps = {}): ReactElement {
414
441
  // Editor will generate CSS and send back via INTERACTIVE_CSS_UPDATE
415
442
  if (typeof window !== 'undefined' && window.parent !== window) {
416
443
  const registryData = Object.fromEntries(InteractiveStylesRegistry.getAll());
417
- window.parent.postMessage({
418
- type: IFRAME_MESSAGE_TYPES.INTERACTIVE_STYLES_UPDATE,
419
- styles: registryData
420
- }, '*');
444
+ window.parent.postMessage(
445
+ {
446
+ type: IFRAME_MESSAGE_TYPES.INTERACTIVE_STYLES_UPDATE,
447
+ styles: registryData,
448
+ },
449
+ '*',
450
+ );
421
451
  }
422
452
 
423
453
  // Wait for React to render before executing JavaScript (unless disabled for editor).
@@ -450,7 +480,7 @@ export function Router(props: RouterProps = {}): ReactElement {
450
480
  // Delay to let DOM fully render
451
481
  const timeoutId = setTimeout(() => {
452
482
  const links = document.querySelectorAll('a[href^="/"]');
453
- links.forEach(link => {
483
+ links.forEach((link) => {
454
484
  const href = link.getAttribute('href');
455
485
  // Skip current page and empty hrefs
456
486
  if (href && href !== currentPath && href !== '#') {
@@ -464,23 +494,31 @@ export function Router(props: RouterProps = {}): ReactElement {
464
494
 
465
495
  // Load components function using RouteLoader
466
496
  // For CMS pages, use the stored template path instead of the URL path
467
- const loadComponents = useCallback(async (path: string) => {
468
- const pathToLoad = cmsTemplatePath || path;
469
- await routeLoader.loadComponents(pathToLoad);
470
- }, [cmsTemplatePath]);
497
+ const loadComponents = useCallback(
498
+ async (path: string) => {
499
+ const pathToLoad = cmsTemplatePath || path;
500
+ await routeLoader.loadComponents(pathToLoad);
501
+ },
502
+ [cmsTemplatePath],
503
+ );
471
504
 
472
505
  // Grace-aware version for HMR: skip reload if iframe just received committed data via postMessage
473
- const loadComponentsForHMR = useCallback(async (path: string) => {
474
- if (Date.now() - lastCommitTimestampRef.current < COMMIT_GRACE_MS) {
475
- return;
476
- }
477
- const pathToLoad = cmsTemplatePath || path;
478
- await routeLoader.loadComponents(pathToLoad);
479
- }, [cmsTemplatePath]);
506
+ const loadComponentsForHMR = useCallback(
507
+ async (path: string) => {
508
+ if (Date.now() - lastCommitTimestampRef.current < COMMIT_GRACE_MS) {
509
+ return;
510
+ }
511
+ const pathToLoad = cmsTemplatePath || path;
512
+ await routeLoader.loadComponents(pathToLoad);
513
+ },
514
+ [cmsTemplatePath],
515
+ );
480
516
 
481
517
  // Ref for loadComponents to avoid recreating effects when cmsTemplatePath changes
482
518
  const loadComponentsRef = useRef(loadComponents);
483
- useEffect(() => { loadComponentsRef.current = loadComponents; }, [loadComponents]);
519
+ useEffect(() => {
520
+ loadComponentsRef.current = loadComponents;
521
+ }, [loadComponents]);
484
522
 
485
523
  // Handle CMS HMR updates - fetch updated collection items directly
486
524
  // Stable callback - always fetches, lets React handle deduplication via setState
@@ -490,9 +528,9 @@ export function Router(props: RouterProps = {}): ReactElement {
490
528
  if (response.ok) {
491
529
  const data = await response.json();
492
530
  // Using functional update - always merges with latest state
493
- setCollectionItemsMap(prev => ({ ...prev, [collection]: data.items || [] }));
531
+ setCollectionItemsMap((prev) => ({ ...prev, [collection]: data.items || [] }));
494
532
  }
495
- } catch (error) {
533
+ } catch (_error) {
496
534
  // Silently fail - CMS refresh is non-critical
497
535
  }
498
536
  }, []); // No dependencies - stable callback
@@ -525,9 +563,15 @@ export function Router(props: RouterProps = {}): ReactElement {
525
563
  delete window.__MENO_CMS__;
526
564
  }
527
565
 
528
- // Initial load
566
+ // Initial load. Gated on the i18n config fetch (deduped with the mount effect
567
+ // above; never rejects) so the first route resolution already knows the locale
568
+ // set — otherwise booting directly at a locale-prefixed path (/pl) races the
569
+ // config fetch and the loader looks up the literal "/pl" page → spurious 404.
529
570
  routeLoader.loadPages();
530
- routeLoader.loadGlobalComponents().then(() => {
571
+ Promise.all([routeLoader.loadGlobalComponents(), fetchI18nConfig()]).then(([, config]) => {
572
+ // Hand the config to the loader here too (idempotent with the config effect
573
+ // above) so the locale parse below never depends on effect ordering.
574
+ routeLoader.setI18nConfig(config);
531
575
  // Use template path for CMS pages, otherwise use the current URL path
532
576
  const pathToLoad = ssrCmsContext ? ssrCmsContext.templatePath : currentPath;
533
577
  loadComponents(pathToLoad);
@@ -576,7 +620,7 @@ export function Router(props: RouterProps = {}): ReactElement {
576
620
  cmsContext,
577
621
  cmsLocale,
578
622
  collectionItemsMap,
579
- templateContext: null
623
+ templateContext: null,
580
624
  });
581
625
  } else if (treeToRender && awaitingCmsContext && previousComponentTree) {
582
626
  // While waiting for CMS context, show previous tree to avoid blink
@@ -590,7 +634,7 @@ export function Router(props: RouterProps = {}): ReactElement {
590
634
  cmsContext,
591
635
  cmsLocale,
592
636
  collectionItemsMap,
593
- templateContext: null
637
+ templateContext: null,
594
638
  });
595
639
  } else if (loading || awaitingCmsContext) {
596
640
  // Show previous content while loading if available
@@ -605,18 +649,20 @@ export function Router(props: RouterProps = {}): ReactElement {
605
649
  cmsContext,
606
650
  cmsLocale,
607
651
  collectionItemsMap,
608
- templateContext: null
652
+ templateContext: null,
609
653
  });
610
654
  } else {
611
655
  // Show subtle spinner while loading
612
- pageContent = h('div', {
613
- style: {
614
- display: 'flex',
615
- justifyContent: 'center',
616
- alignItems: 'center',
617
- height: '100vh'
618
- }
619
- },
656
+ pageContent = h(
657
+ 'div',
658
+ {
659
+ style: {
660
+ display: 'flex',
661
+ justifyContent: 'center',
662
+ alignItems: 'center',
663
+ height: '100vh',
664
+ },
665
+ },
620
666
  h('style', null, '@keyframes meno-spin { to { transform: rotate(360deg); } }'),
621
667
  h('div', {
622
668
  style: {
@@ -625,49 +671,57 @@ export function Router(props: RouterProps = {}): ReactElement {
625
671
  border: '2px solid #e5e7eb',
626
672
  borderTopColor: '#6b7280',
627
673
  borderRadius: '50%',
628
- animation: 'meno-spin 0.6s linear infinite'
629
- }
630
- })
674
+ animation: 'meno-spin 0.6s linear infinite',
675
+ },
676
+ }),
631
677
  );
632
678
  }
633
679
  } else if (showNotFound) {
634
- pageContent = h('div', {
635
- style: {
636
- textAlign: 'center',
637
- padding: '40px',
638
- maxWidth: '800px',
639
- margin: '0 auto'
640
- }
641
- },
680
+ pageContent = h(
681
+ 'div',
682
+ {
683
+ style: {
684
+ textAlign: 'center',
685
+ padding: '40px',
686
+ maxWidth: '800px',
687
+ margin: '0 auto',
688
+ },
689
+ },
642
690
  h('h2', null, `Page not found: ${currentPath}`),
643
- h('p', { style: { marginTop: '16px', marginBottom: '24px', color: '#666' } },
644
- 'Available pages:'
691
+ h('p', { style: { marginTop: '16px', marginBottom: '24px', color: '#666' } }, 'Available pages:'),
692
+ h(
693
+ 'ul',
694
+ {
695
+ style: {
696
+ listStyle: 'none',
697
+ padding: 0,
698
+ display: 'flex',
699
+ flexDirection: 'column',
700
+ gap: '12px',
701
+ alignItems: 'center',
702
+ },
703
+ },
704
+ availablePages.map((page, i) =>
705
+ h(
706
+ 'li',
707
+ { key: i },
708
+ h(
709
+ 'a',
710
+ {
711
+ href: page,
712
+ onClick: createNavigationHandler(page),
713
+ style: {
714
+ color: '#0070f3',
715
+ textDecoration: 'none',
716
+ fontSize: '18px',
717
+ fontWeight: '600',
718
+ },
719
+ },
720
+ page === '/' ? 'Home (/)' : page,
721
+ ),
722
+ ),
723
+ ),
645
724
  ),
646
- h('ul', {
647
- style: {
648
- listStyle: 'none',
649
- padding: 0,
650
- display: 'flex',
651
- flexDirection: 'column',
652
- gap: '12px',
653
- alignItems: 'center'
654
- }
655
- },
656
- availablePages.map((page, i) =>
657
- h('li', { key: i },
658
- h('a', {
659
- href: page,
660
- onClick: createNavigationHandler(page),
661
- style: {
662
- color: '#0070f3',
663
- textDecoration: 'none',
664
- fontSize: '18px',
665
- fontWeight: '600'
666
- }
667
- }, page === '/' ? 'Home (/)' : page)
668
- )
669
- )
670
- )
671
725
  );
672
726
  } else if (previousComponentTree) {
673
727
  // Keep previous content visible during timeout (waiting to determine if not found)
@@ -681,21 +735,23 @@ export function Router(props: RouterProps = {}): ReactElement {
681
735
  cmsContext,
682
736
  cmsLocale,
683
737
  collectionItemsMap,
684
- templateContext: null
738
+ templateContext: null,
685
739
  });
686
740
  }
687
741
 
688
742
  // Fallback: if no content matched, show spinner
689
743
  // This prevents empty flash when loading=false but componentTree=null
690
744
  if (!pageContent) {
691
- pageContent = h('div', {
692
- style: {
693
- display: 'flex',
694
- justifyContent: 'center',
695
- alignItems: 'center',
696
- height: '100vh'
697
- }
698
- },
745
+ pageContent = h(
746
+ 'div',
747
+ {
748
+ style: {
749
+ display: 'flex',
750
+ justifyContent: 'center',
751
+ alignItems: 'center',
752
+ height: '100vh',
753
+ },
754
+ },
699
755
  h('style', null, '@keyframes meno-spin { to { transform: rotate(360deg); } }'),
700
756
  h('div', {
701
757
  style: {
@@ -704,20 +760,21 @@ export function Router(props: RouterProps = {}): ReactElement {
704
760
  border: '2px solid #e5e7eb',
705
761
  borderTopColor: '#6b7280',
706
762
  borderRadius: '50%',
707
- animation: 'meno-spin 0.6s linear infinite'
708
- }
709
- })
763
+ animation: 'meno-spin 0.6s linear infinite',
764
+ },
765
+ }),
710
766
  );
711
767
  }
712
768
 
713
769
  // Render HMRManager once at the top level with page content
714
- return h('div', null,
770
+ return h(
771
+ 'div',
772
+ null,
715
773
  h(HMRManager, {
716
774
  onReload: loadComponentsForHMR,
717
775
  onCMSUpdate: handleCMSUpdate,
718
776
  currentPath: currentPath,
719
777
  }),
720
- pageContent
778
+ pageContent,
721
779
  );
722
780
  }
723
-