meno-core 1.0.53 → 1.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/.claude/settings.local.json +1 -3
  2. package/bin/cli.ts +48 -57
  3. package/build-astro.ts +131 -113
  4. package/build-next.ts +109 -96
  5. package/build-static.test.ts +39 -10
  6. package/build-static.ts +120 -122
  7. package/dist/bin/cli.js +34 -38
  8. package/dist/bin/cli.js.map +2 -2
  9. package/dist/build-static.js +12 -11
  10. package/dist/chunks/chunk-2AR55GYH.js +42 -0
  11. package/dist/chunks/chunk-2AR55GYH.js.map +7 -0
  12. package/dist/chunks/{chunk-IGYR22T6.js → chunk-2FN4UOVO.js} +512 -239
  13. package/dist/chunks/chunk-2FN4UOVO.js.map +7 -0
  14. package/dist/chunks/chunk-3XER4E5W.js +168 -0
  15. package/dist/chunks/chunk-3XER4E5W.js.map +7 -0
  16. package/dist/chunks/{chunk-X754AHS5.js → chunk-5ETZFREW.js} +9 -12
  17. package/dist/chunks/chunk-5ETZFREW.js.map +7 -0
  18. package/dist/chunks/{chunk-2MHDV5BF.js → chunk-7E4IF5L7.js} +15 -21
  19. package/dist/chunks/chunk-7E4IF5L7.js.map +7 -0
  20. package/dist/chunks/{chunk-JGWFTO6P.js → chunk-7HWQUVTU.js} +1578 -1349
  21. package/dist/chunks/chunk-7HWQUVTU.js.map +7 -0
  22. package/dist/chunks/{chunk-O3NAGJP4.js → chunk-AE3QK5QW.js} +110 -21
  23. package/dist/chunks/chunk-AE3QK5QW.js.map +7 -0
  24. package/dist/chunks/{chunk-GZHGVVW3.js → chunk-F6KTJYGV.js} +7 -7
  25. package/dist/chunks/chunk-F6KTJYGV.js.map +7 -0
  26. package/dist/chunks/{chunk-WQFG7PAH.js → chunk-FZITJSSS.js} +2 -6
  27. package/dist/chunks/chunk-FZITJSSS.js.map +7 -0
  28. package/dist/chunks/{chunk-QB2LNO4W.js → chunk-GSYYA5GX.js} +2 -2
  29. package/dist/chunks/chunk-GSYYA5GX.js.map +7 -0
  30. package/dist/chunks/{chunk-YBLHKYFF.js → chunk-HIZMY3EP.js} +1 -1
  31. package/dist/chunks/chunk-HIZMY3EP.js.map +7 -0
  32. package/dist/chunks/{chunk-AZQYF6KE.js → chunk-I2WEGYA7.js} +41 -176
  33. package/dist/chunks/chunk-I2WEGYA7.js.map +7 -0
  34. package/dist/chunks/{chunk-I7YIGZXT.js → chunk-JNO3CNLJ.js} +6 -9
  35. package/dist/chunks/chunk-JNO3CNLJ.js.map +7 -0
  36. package/dist/chunks/{chunk-UB44F4Z2.js → chunk-NVRBTSQG.js} +2 -4
  37. package/dist/chunks/chunk-NVRBTSQG.js.map +7 -0
  38. package/dist/chunks/{chunk-JGP5A3Y5.js → chunk-Q4OBWKXG.js} +40 -33
  39. package/dist/chunks/chunk-Q4OBWKXG.js.map +7 -0
  40. package/dist/chunks/{chunk-R6XHAFBF.js → chunk-QTE32Y53.js} +250 -242
  41. package/dist/chunks/chunk-QTE32Y53.js.map +7 -0
  42. package/dist/chunks/{chunk-H3GJ4H2U.js → chunk-STDY3OVM.js} +214 -85
  43. package/dist/chunks/chunk-STDY3OVM.js.map +7 -0
  44. package/dist/chunks/configService-PRJZF7Y6.js +14 -0
  45. package/dist/chunks/{constants-STK2YBIW.js → constants-KIQEYMAM.js} +2 -2
  46. package/dist/chunks/{fs-JGINUXGL.js → fs-ZI5JEU7V.js} +2 -2
  47. package/dist/entries/server-router.js +14 -19
  48. package/dist/entries/server-router.js.map +2 -2
  49. package/dist/lib/client/index.js +638 -332
  50. package/dist/lib/client/index.js.map +2 -2
  51. package/dist/lib/server/index.js +177 -235
  52. package/dist/lib/server/index.js.map +2 -2
  53. package/dist/lib/shared/index.js +80 -44
  54. package/dist/lib/shared/index.js.map +2 -2
  55. package/dist/lib/shared/richtext/index.js +1 -1
  56. package/dist/lib/test-utils/index.js +38 -60
  57. package/dist/lib/test-utils/index.js.map +2 -2
  58. package/entries/client-router.tsx +10 -8
  59. package/entries/server-router.tsx +1 -7
  60. package/lib/client/ClientInitializer.ts +8 -8
  61. package/lib/client/ErrorBoundary.test.tsx +146 -143
  62. package/lib/client/ErrorBoundary.tsx +175 -127
  63. package/lib/client/componentRegistry.test.ts +96 -108
  64. package/lib/client/componentRegistry.ts +1 -2
  65. package/lib/client/contexts/ThemeContext.tsx +3 -2
  66. package/lib/client/core/ComponentBuilder.test.ts +513 -560
  67. package/lib/client/core/ComponentBuilder.ts +318 -146
  68. package/lib/client/core/ComponentRenderer.test.tsx +1 -2
  69. package/lib/client/core/ComponentRenderer.tsx +46 -33
  70. package/lib/client/core/builders/embedBuilder.ts +241 -53
  71. package/lib/client/core/builders/linkBuilder.ts +71 -44
  72. package/lib/client/core/builders/linkNodeBuilder.ts +78 -53
  73. package/lib/client/core/builders/listBuilder.ts +115 -86
  74. package/lib/client/core/builders/localeListBuilder.ts +95 -60
  75. package/lib/client/core/builders/types.ts +5 -5
  76. package/lib/client/core/cmsTemplateProcessor.ts +7 -7
  77. package/lib/client/elementRegistry.ts +3 -3
  78. package/lib/client/fontFamiliesService.test.ts +2 -10
  79. package/lib/client/fontFamiliesService.ts +3 -3
  80. package/lib/client/hmr/HMRManager.tsx +8 -0
  81. package/lib/client/hmrCssReload.ts +14 -8
  82. package/lib/client/hmrWebSocket.ts +9 -14
  83. package/lib/client/hooks/useColorVariables.test.ts +21 -21
  84. package/lib/client/hooks/useColorVariables.ts +12 -10
  85. package/lib/client/hooks/usePropertyAutocomplete.ts +3 -5
  86. package/lib/client/hooks/useVariables.ts +4 -4
  87. package/lib/client/hydration/HydrationUtils.test.ts +24 -25
  88. package/lib/client/hydration/HydrationUtils.ts +3 -4
  89. package/lib/client/i18nConfigService.test.ts +2 -7
  90. package/lib/client/i18nConfigService.ts +2 -2
  91. package/lib/client/meno-filter/MenoFilter.test.ts +19 -21
  92. package/lib/client/meno-filter/MenoFilter.ts +5 -9
  93. package/lib/client/meno-filter/bindings.ts +15 -40
  94. package/lib/client/meno-filter/init.ts +1 -1
  95. package/lib/client/meno-filter/renderer.ts +23 -29
  96. package/lib/client/meno-filter/script.generated.ts +1 -3
  97. package/lib/client/meno-filter/ui.ts +3 -5
  98. package/lib/client/meno-filter/updates.ts +15 -21
  99. package/lib/client/navigation.test.ts +159 -159
  100. package/lib/client/navigation.ts +0 -1
  101. package/lib/client/responsiveStyleResolver.test.ts +230 -228
  102. package/lib/client/responsiveStyleResolver.ts +13 -16
  103. package/lib/client/routing/RouteLoader.test.ts +23 -24
  104. package/lib/client/routing/RouteLoader.ts +22 -35
  105. package/lib/client/routing/Router.tsx +31 -3
  106. package/lib/client/scripts/ScriptExecutor.test.ts +157 -158
  107. package/lib/client/scripts/ScriptExecutor.ts +15 -33
  108. package/lib/client/services/PrefetchService.test.ts +2 -2
  109. package/lib/client/services/PrefetchService.ts +10 -24
  110. package/lib/client/styleProcessor.test.ts +9 -9
  111. package/lib/client/styleProcessor.ts +18 -15
  112. package/lib/client/styles/StyleInjector.test.ts +122 -115
  113. package/lib/client/styles/StyleInjector.ts +9 -6
  114. package/lib/client/styles/UtilityClassCollector.ts +19 -26
  115. package/lib/client/styles/cspNonce.test.ts +2 -5
  116. package/lib/client/templateEngine.test.ts +554 -482
  117. package/lib/client/templateEngine.ts +200 -64
  118. package/lib/client/theme.ts +0 -1
  119. package/lib/client/utils/toast.ts +0 -1
  120. package/lib/server/__integration__/api-routes.test.ts +8 -4
  121. package/lib/server/__integration__/cms-integration.test.ts +1 -4
  122. package/lib/server/__integration__/server-lifecycle.test.ts +2 -5
  123. package/lib/server/__integration__/ssr-rendering.test.ts +47 -37
  124. package/lib/server/__integration__/static-assets.test.ts +1 -1
  125. package/lib/server/__integration__/test-helpers.ts +84 -70
  126. package/lib/server/ab/generateFunctions.ts +12 -10
  127. package/lib/server/astro/cmsPageEmitter.ts +23 -38
  128. package/lib/server/astro/componentEmitter.ts +25 -36
  129. package/lib/server/astro/cssCollector.ts +10 -26
  130. package/lib/server/astro/nodeToAstro.test.ts +1750 -30
  131. package/lib/server/astro/nodeToAstro.ts +198 -187
  132. package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +105 -109
  133. package/lib/server/astro/normalizeOrphanTemplateProps.ts +4 -12
  134. package/lib/server/astro/pageEmitter.ts +9 -13
  135. package/lib/server/astro/tailwindMapper.test.ts +10 -37
  136. package/lib/server/astro/tailwindMapper.ts +33 -40
  137. package/lib/server/astro/templateTransformer.ts +14 -17
  138. package/lib/server/createServer.ts +5 -17
  139. package/lib/server/cssGenerator.test.ts +35 -44
  140. package/lib/server/cssGenerator.ts +6 -17
  141. package/lib/server/fileWatcher.test.ts +124 -10
  142. package/lib/server/fileWatcher.ts +124 -118
  143. package/lib/server/index.ts +7 -1
  144. package/lib/server/jsonLoader.test.ts +39 -2
  145. package/lib/server/jsonLoader.ts +33 -31
  146. package/lib/server/middleware/cors.test.ts +20 -20
  147. package/lib/server/middleware/cors.ts +28 -4
  148. package/lib/server/middleware/errorHandler.test.ts +5 -3
  149. package/lib/server/middleware/errorHandler.ts +3 -8
  150. package/lib/server/middleware/index.ts +0 -1
  151. package/lib/server/middleware/logger.test.ts +7 -5
  152. package/lib/server/middleware/logger.ts +10 -22
  153. package/lib/server/pageCache.test.ts +76 -77
  154. package/lib/server/pageCache.ts +0 -1
  155. package/lib/server/projectContext.ts +4 -3
  156. package/lib/server/providers/fileSystemCMSProvider.test.ts +124 -95
  157. package/lib/server/providers/fileSystemCMSProvider.ts +35 -20
  158. package/lib/server/providers/fileSystemPageProvider.test.ts +84 -0
  159. package/lib/server/providers/fileSystemPageProvider.ts +31 -12
  160. package/lib/server/routes/api/cms.test.ts +26 -14
  161. package/lib/server/routes/api/cms.ts +9 -14
  162. package/lib/server/routes/api/components.ts +30 -34
  163. package/lib/server/routes/api/config.ts +0 -1
  164. package/lib/server/routes/api/core-routes.ts +47 -74
  165. package/lib/server/routes/api/functions.ts +8 -16
  166. package/lib/server/routes/api/index.ts +3 -6
  167. package/lib/server/routes/api/pages.ts +8 -11
  168. package/lib/server/routes/api/shared.test.ts +1 -1
  169. package/lib/server/routes/api/shared.ts +12 -9
  170. package/lib/server/routes/api/variables.test.ts +1 -3
  171. package/lib/server/routes/api/variables.ts +1 -1
  172. package/lib/server/routes/index.ts +23 -26
  173. package/lib/server/routes/pages.ts +34 -29
  174. package/lib/server/routes/static.ts +16 -4
  175. package/lib/server/runtime/bundler.ts +47 -32
  176. package/lib/server/runtime/fs.ts +3 -13
  177. package/lib/server/runtime/httpServer.ts +5 -9
  178. package/lib/server/services/ColorService.ts +32 -27
  179. package/lib/server/services/EnumService.test.ts +2 -6
  180. package/lib/server/services/EnumService.ts +7 -2
  181. package/lib/server/services/VariableService.test.ts +1 -5
  182. package/lib/server/services/VariableService.ts +6 -1
  183. package/lib/server/services/cmsService.test.ts +116 -78
  184. package/lib/server/services/cmsService.ts +24 -54
  185. package/lib/server/services/componentService.test.ts +122 -36
  186. package/lib/server/services/componentService.ts +54 -38
  187. package/lib/server/services/configService.test.ts +9 -31
  188. package/lib/server/services/configService.ts +20 -27
  189. package/lib/server/services/fileWatcherService.ts +40 -6
  190. package/lib/server/services/index.ts +0 -1
  191. package/lib/server/services/pageService.test.ts +1 -3
  192. package/lib/server/services/pageService.ts +14 -13
  193. package/lib/server/ssr/attributeBuilder.ts +16 -6
  194. package/lib/server/ssr/buildErrorOverlay.ts +11 -12
  195. package/lib/server/ssr/clientDataInjector.ts +7 -21
  196. package/lib/server/ssr/cmsSSRProcessor.ts +3 -6
  197. package/lib/server/ssr/cssCollector.ts +1 -1
  198. package/lib/server/ssr/errorOverlay.test.ts +1 -1
  199. package/lib/server/ssr/errorOverlay.ts +3 -9
  200. package/lib/server/ssr/htmlGenerator.nonce.test.ts +3 -9
  201. package/lib/server/ssr/htmlGenerator.test.ts +120 -43
  202. package/lib/server/ssr/htmlGenerator.ts +120 -85
  203. package/lib/server/ssr/imageMetadata.test.ts +3 -1
  204. package/lib/server/ssr/imageMetadata.ts +25 -19
  205. package/lib/server/ssr/jsCollector.test.ts +3 -13
  206. package/lib/server/ssr/jsCollector.ts +3 -8
  207. package/lib/server/ssr/liveReloadIntegration.test.ts +69 -28
  208. package/lib/server/ssr/metaTagGenerator.ts +2 -2
  209. package/lib/server/ssr/ssrRenderer.branches.test.ts +1103 -0
  210. package/lib/server/ssr/ssrRenderer.test.ts +196 -246
  211. package/lib/server/ssr/ssrRenderer.ts +609 -225
  212. package/lib/server/ssrRenderer.test.ts +1044 -950
  213. package/lib/server/utils/jsonLineMapper.test.ts +28 -28
  214. package/lib/server/utils/jsonLineMapper.ts +1 -1
  215. package/lib/server/validateStyleCoverage.ts +18 -20
  216. package/lib/server/webflow/buildWebflow.ts +41 -53
  217. package/lib/server/webflow/nodeToWebflow.test.ts +150 -218
  218. package/lib/server/webflow/nodeToWebflow.ts +195 -258
  219. package/lib/server/webflow/styleMapper.test.ts +15 -56
  220. package/lib/server/webflow/styleMapper.ts +33 -41
  221. package/lib/server/webflow/types.ts +1 -8
  222. package/lib/server/websocketManager.ts +16 -19
  223. package/lib/shared/attributeNodeUtils.test.ts +15 -15
  224. package/lib/shared/attributeNodeUtils.ts +5 -12
  225. package/lib/shared/breakpoints.ts +4 -11
  226. package/lib/shared/cmsQueryParser.test.ts +50 -42
  227. package/lib/shared/cmsQueryParser.ts +49 -31
  228. package/lib/shared/colorVariableUtils.test.ts +5 -5
  229. package/lib/shared/colorVariableUtils.ts +3 -8
  230. package/lib/shared/componentRefs.ts +1 -5
  231. package/lib/shared/constants.test.ts +3 -3
  232. package/lib/shared/constants.ts +4 -8
  233. package/lib/shared/cssGeneration.test.ts +262 -144
  234. package/lib/shared/cssGeneration.ts +189 -516
  235. package/lib/shared/cssNamedColors.ts +152 -30
  236. package/lib/shared/cssProperties.test.ts +5 -6
  237. package/lib/shared/cssProperties.ts +296 -112
  238. package/lib/shared/elementClassName.test.ts +109 -109
  239. package/lib/shared/elementClassName.ts +1 -1
  240. package/lib/shared/elementUtils.ts +12 -16
  241. package/lib/shared/errorLogger.ts +2 -10
  242. package/lib/shared/errors.test.ts +2 -13
  243. package/lib/shared/errors.ts +2 -8
  244. package/lib/shared/expressionEvaluator.test.ts +119 -0
  245. package/lib/shared/expressionEvaluator.ts +43 -24
  246. package/lib/shared/fontLoader.test.ts +19 -5
  247. package/lib/shared/friendlyError.ts +2 -3
  248. package/lib/shared/gradientUtils.test.ts +1 -5
  249. package/lib/shared/gradientUtils.ts +2 -6
  250. package/lib/shared/hrefRefs.ts +2 -10
  251. package/lib/shared/i18n.test.ts +1 -1
  252. package/lib/shared/i18n.ts +13 -34
  253. package/lib/shared/index.ts +4 -0
  254. package/lib/shared/inlineSvgStyleRules.ts +2 -4
  255. package/lib/shared/interactiveStyleMappings.test.ts +11 -33
  256. package/lib/shared/interactiveStyleMappings.ts +9 -16
  257. package/lib/shared/interactiveStyles.test.ts +165 -188
  258. package/lib/shared/interfaces/contentProvider.ts +1 -1
  259. package/lib/shared/itemTemplateUtils.test.ts +6 -12
  260. package/lib/shared/itemTemplateUtils.ts +19 -35
  261. package/lib/shared/jsonRepair.ts +8 -2
  262. package/lib/shared/libraryLoader.test.ts +15 -49
  263. package/lib/shared/libraryLoader.ts +7 -22
  264. package/lib/shared/netlifyLocale404.test.ts +179 -0
  265. package/lib/shared/netlifyLocale404.ts +110 -0
  266. package/lib/shared/nodeUtils.test.ts +24 -16
  267. package/lib/shared/nodeUtils.ts +49 -19
  268. package/lib/shared/pathArrayUtils.test.ts +1 -2
  269. package/lib/shared/pathArrayUtils.ts +1 -1
  270. package/lib/shared/pathSecurity.ts +1 -1
  271. package/lib/shared/pathUtils.test.ts +4 -6
  272. package/lib/shared/pathUtils.ts +42 -48
  273. package/lib/shared/paths/Path.test.ts +2 -2
  274. package/lib/shared/paths/Path.ts +0 -1
  275. package/lib/shared/paths/PathConverter.test.ts +1 -1
  276. package/lib/shared/paths/PathConverter.ts +14 -17
  277. package/lib/shared/paths/PathUtils.ts +9 -10
  278. package/lib/shared/paths/PathValidator.test.ts +2 -15
  279. package/lib/shared/paths/PathValidator.ts +11 -9
  280. package/lib/shared/paths/index.ts +1 -2
  281. package/lib/shared/propResolver.test.ts +240 -244
  282. package/lib/shared/propResolver.ts +14 -25
  283. package/lib/shared/pxToRem.test.ts +7 -6
  284. package/lib/shared/pxToRem.ts +2 -5
  285. package/lib/shared/registry/BaseNodeTypeRegistry.test.ts +9 -5
  286. package/lib/shared/registry/ClientRegistry.ts +0 -1
  287. package/lib/shared/registry/ComponentRegistry.test.ts +43 -29
  288. package/lib/shared/registry/ComponentRegistry.ts +9 -11
  289. package/lib/shared/registry/NodeTypeDefinition.ts +15 -8
  290. package/lib/shared/registry/RegistryManager.ts +1 -2
  291. package/lib/shared/registry/SSRRegistry.ts +0 -1
  292. package/lib/shared/registry/createNodeType.ts +7 -9
  293. package/lib/shared/registry/defineNodeType.ts +2 -6
  294. package/lib/shared/registry/index.ts +0 -1
  295. package/lib/shared/registry/nodeTypes/ComponentInstanceNodeType.ts +14 -15
  296. package/lib/shared/registry/nodeTypes/EmbedNodeType.ts +18 -11
  297. package/lib/shared/registry/nodeTypes/HtmlNodeType.ts +47 -18
  298. package/lib/shared/registry/nodeTypes/LinkNodeType.ts +21 -19
  299. package/lib/shared/registry/nodeTypes/ListNodeType.ts +78 -74
  300. package/lib/shared/registry/nodeTypes/LocaleListNodeType.ts +27 -21
  301. package/lib/shared/registry/nodeTypes/SlotMarkerType.ts +6 -7
  302. package/lib/shared/registry/nodeTypes/index.ts +10 -2
  303. package/lib/shared/responsiveScaling.test.ts +15 -31
  304. package/lib/shared/responsiveScaling.ts +55 -37
  305. package/lib/shared/responsiveStyleUtils.ts +11 -13
  306. package/lib/shared/richtext/htmlToTiptap.test.ts +23 -14
  307. package/lib/shared/richtext/htmlToTiptap.ts +1 -3
  308. package/lib/shared/richtext/tiptapToHtml.test.ts +5 -6
  309. package/lib/shared/richtext/types.ts +1 -8
  310. package/lib/shared/slugTranslator.test.ts +13 -13
  311. package/lib/shared/slugTranslator.ts +12 -16
  312. package/lib/shared/slugify.ts +9 -15
  313. package/lib/shared/styleNodeUtils.test.ts +8 -8
  314. package/lib/shared/styleNodeUtils.ts +5 -10
  315. package/lib/shared/styleUtils.test.ts +87 -61
  316. package/lib/shared/styleUtils.ts +5 -6
  317. package/lib/shared/themeDefaults.test.ts +11 -11
  318. package/lib/shared/themeDefaults.ts +3 -4
  319. package/lib/shared/tree/PathBuilder.test.ts +62 -138
  320. package/lib/shared/tree/PathBuilder.ts +49 -39
  321. package/lib/shared/treePathUtils.test.ts +2 -10
  322. package/lib/shared/treePathUtils.ts +54 -59
  323. package/lib/shared/types/api.ts +1 -2
  324. package/lib/shared/types/cms.ts +25 -21
  325. package/lib/shared/types/comment.ts +49 -16
  326. package/lib/shared/types/components.ts +27 -25
  327. package/lib/shared/types/errors.test.ts +1 -6
  328. package/lib/shared/types/errors.ts +3 -7
  329. package/lib/shared/types/experiments.ts +28 -28
  330. package/lib/shared/types/index.ts +2 -2
  331. package/lib/shared/types/styles.ts +0 -1
  332. package/lib/shared/types/variables.test.ts +4 -13
  333. package/lib/shared/types/variables.ts +48 -27
  334. package/lib/shared/types.ts +1 -2
  335. package/lib/shared/utilityClassConfig.ts +648 -321
  336. package/lib/shared/utilityClassMapper.test.ts +203 -92
  337. package/lib/shared/utilityClassMapper.ts +188 -246
  338. package/lib/shared/utilityClassNames.ts +326 -0
  339. package/lib/shared/utils.test.ts +2 -10
  340. package/lib/shared/utils.ts +19 -10
  341. package/lib/shared/validation/cmsValidators.ts +2 -1
  342. package/lib/shared/validation/commentValidators.test.ts +53 -0
  343. package/lib/shared/validation/commentValidators.ts +12 -1
  344. package/lib/shared/validation/propValidator.test.ts +18 -20
  345. package/lib/shared/validation/propValidator.ts +12 -17
  346. package/lib/shared/validation/schemas.test.ts +24 -33
  347. package/lib/shared/validation/schemas.ts +469 -344
  348. package/lib/shared/validation/validators.test.ts +1 -6
  349. package/lib/shared/validation/validators.ts +89 -68
  350. package/lib/shared/viewportUnits.integration.test.ts +14 -10
  351. package/lib/shared/viewportUnits.test.ts +11 -23
  352. package/lib/test-utils/dom-setup.ts +1 -1
  353. package/lib/test-utils/factories/ConsoleMockFactory.ts +3 -7
  354. package/lib/test-utils/factories/DomMockFactory.ts +7 -19
  355. package/lib/test-utils/factories/EventMockFactory.ts +7 -13
  356. package/lib/test-utils/factories/FetchMockFactory.ts +39 -57
  357. package/lib/test-utils/factories/ServerMockFactory.ts +5 -9
  358. package/lib/test-utils/factories/StoreMockFactory.ts +14 -25
  359. package/lib/test-utils/fixtures.ts +45 -45
  360. package/lib/test-utils/helpers/asyncHelpers.test.ts +15 -18
  361. package/lib/test-utils/helpers/asyncHelpers.ts +11 -20
  362. package/lib/test-utils/helpers.ts +1 -5
  363. package/lib/test-utils/index.ts +0 -4
  364. package/lib/test-utils/mockFactories.ts +12 -18
  365. package/lib/test-utils/mocks.ts +4 -2
  366. package/package.json +1 -1
  367. package/scripts/build-meno-filter.ts +1 -4
  368. package/vite.config.ts +4 -4
  369. package/dist/chunks/chunk-2MHDV5BF.js.map +0 -7
  370. package/dist/chunks/chunk-AZQYF6KE.js.map +0 -7
  371. package/dist/chunks/chunk-GZHGVVW3.js.map +0 -7
  372. package/dist/chunks/chunk-H3GJ4H2U.js.map +0 -7
  373. package/dist/chunks/chunk-I7YIGZXT.js.map +0 -7
  374. package/dist/chunks/chunk-IGYR22T6.js.map +0 -7
  375. package/dist/chunks/chunk-JGP5A3Y5.js.map +0 -7
  376. package/dist/chunks/chunk-JGWFTO6P.js.map +0 -7
  377. package/dist/chunks/chunk-O3NAGJP4.js.map +0 -7
  378. package/dist/chunks/chunk-QB2LNO4W.js.map +0 -7
  379. package/dist/chunks/chunk-R6XHAFBF.js.map +0 -7
  380. package/dist/chunks/chunk-UB44F4Z2.js.map +0 -7
  381. package/dist/chunks/chunk-WQFG7PAH.js.map +0 -7
  382. package/dist/chunks/chunk-X754AHS5.js.map +0 -7
  383. package/dist/chunks/chunk-YBLHKYFF.js.map +0 -7
  384. package/dist/chunks/configService-R3OGU2UD.js +0 -13
  385. /package/dist/chunks/{configService-R3OGU2UD.js.map → configService-PRJZF7Y6.js.map} +0 -0
  386. /package/dist/chunks/{constants-STK2YBIW.js.map → constants-KIQEYMAM.js.map} +0 -0
  387. /package/dist/chunks/{fs-JGINUXGL.js.map → fs-ZI5JEU7V.js.map} +0 -0
package/build-astro.ts CHANGED
@@ -4,49 +4,54 @@
4
4
  * with a shared layout, global CSS, and optional CMS content collections.
5
5
  */
6
6
 
7
- import { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync, writeFileSync } from "fs";
8
- import { writeFile, readFile } from "fs/promises";
9
- import { join } from "path";
10
- import { createHash } from "crypto";
7
+ import { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync, writeFileSync } from 'fs';
8
+ import { writeFile, readFile } from 'fs/promises';
9
+ import { join } from 'path';
10
+ import { createHash } from 'crypto';
11
11
  import { inspect, minifyJS as runtimeMinifyJS } from './lib/server/runtime';
12
12
  import {
13
13
  loadJSONFile,
14
14
  loadComponentDirectory,
15
15
  mapPageNameToPath,
16
16
  parseJSON,
17
- loadI18nConfig
18
- } from "./lib/server/jsonLoader";
19
- import { generateSSRHTML } from "./lib/server/ssrRenderer";
20
- import type { SSRHTMLResult } from "./lib/server/ssr/htmlGenerator";
21
- import { projectPaths } from "./lib/server/projectContext";
22
- import { loadProjectConfig, generateFontCSS, generateFontPreloadTags } from "./lib/shared/fontLoader";
23
- import { FileSystemCMSProvider } from "./lib/server/providers/fileSystemCMSProvider";
24
- import { CMSService } from "./lib/server/services/cmsService";
25
- import { isI18nValue, resolveI18nValue } from "./lib/shared/i18n";
26
- import { tiptapToHtml } from "./lib/shared/richtext/tiptapToHtml";
27
- import { isTiptapDocument } from "./lib/shared/richtext/types";
28
- import type { ComponentDefinition, JSONPage, CMSSchema, CMSItem, I18nConfig } from "./lib/shared/types";
29
- import type { CMSFieldDefinition } from "./lib/shared/types/cms";
30
- import { isItemDraftForLocale } from "./lib/shared/types";
31
- import { CMS_DRAFT_SUFFIX } from "./lib/shared/pathSecurity";
32
- import type { SlugMap } from "./lib/shared/slugTranslator";
33
- import { renderPageSSR } from "./lib/server/ssr/ssrRenderer";
34
- import { generateThemeColorVariablesCSS, generateVariablesCSS } from "./lib/server/cssGenerator";
35
- import { colorService } from "./lib/server/services/ColorService";
36
- import { variableService } from "./lib/server/services/VariableService";
37
- import { configService } from "./lib/server/services/configService";
38
- import { loadBreakpointConfig, loadIconsConfig } from "./lib/server/jsonLoader";
39
- import type { InteractiveStyles } from "./lib/shared/types/styles";
40
- import { collectComponentLibraries, filterLibrariesByContext, mergeLibraries, generateLibraryTags } from "./lib/shared/libraryLoader";
41
- import { migrateTemplatesDirectory } from "./lib/server/migrateTemplates";
42
- import { emitAstroComponent } from "./lib/server/astro/componentEmitter";
43
- import { emitAstroPage } from "./lib/server/astro/pageEmitter";
44
- import { normalizeOrphanTemplateProps } from "./lib/server/astro/normalizeOrphanTemplateProps";
17
+ loadI18nConfig,
18
+ } from './lib/server/jsonLoader';
19
+ import { generateSSRHTML } from './lib/server/ssrRenderer';
20
+ import type { SSRHTMLResult } from './lib/server/ssr/htmlGenerator';
21
+ import { projectPaths } from './lib/server/projectContext';
22
+ import { loadProjectConfig, generateFontCSS, generateFontPreloadTags } from './lib/shared/fontLoader';
23
+ import { FileSystemCMSProvider } from './lib/server/providers/fileSystemCMSProvider';
24
+ import { CMSService } from './lib/server/services/cmsService';
25
+ import { isI18nValue, resolveI18nValue } from './lib/shared/i18n';
26
+ import { syncNetlifyLocale404Block } from './lib/shared/netlifyLocale404';
27
+ import { tiptapToHtml } from './lib/shared/richtext/tiptapToHtml';
28
+ import { isTiptapDocument } from './lib/shared/richtext/types';
29
+ import type { ComponentDefinition, JSONPage, CMSSchema, CMSItem, I18nConfig } from './lib/shared/types';
30
+ import type { CMSFieldDefinition } from './lib/shared/types/cms';
31
+ import { isItemDraftForLocale } from './lib/shared/types';
32
+ import { CMS_DRAFT_SUFFIX } from './lib/shared/pathSecurity';
33
+ import type { SlugMap } from './lib/shared/slugTranslator';
34
+ import { renderPageSSR } from './lib/server/ssr/ssrRenderer';
35
+ import { generateThemeColorVariablesCSS, generateVariablesCSS } from './lib/server/cssGenerator';
36
+ import { colorService } from './lib/server/services/ColorService';
37
+ import { variableService } from './lib/server/services/VariableService';
38
+ import { configService } from './lib/server/services/configService';
39
+ import { loadBreakpointConfig, loadIconsConfig } from './lib/server/jsonLoader';
40
+ import type { InteractiveStyles } from './lib/shared/types/styles';
41
+ import {
42
+ collectComponentLibraries,
43
+ filterLibrariesByContext,
44
+ mergeLibraries,
45
+ generateLibraryTags,
46
+ } from './lib/shared/libraryLoader';
47
+ import { migrateTemplatesDirectory } from './lib/server/migrateTemplates';
48
+ import { emitAstroComponent } from './lib/server/astro/componentEmitter';
49
+ import { emitAstroPage } from './lib/server/astro/pageEmitter';
50
+ import { normalizeOrphanTemplateProps } from './lib/server/astro/normalizeOrphanTemplateProps';
45
51
  import { emitCMSPage, CMS_SLUG_PLACEHOLDER } from './lib/server/astro/cmsPageEmitter';
46
- import { collectAllMappingClasses } from "./lib/server/astro/cssCollector";
47
- import { buildImageMetadataMap, RESPONSIVE_WIDTHS } from "./lib/server/ssr/imageMetadata";
48
- import { needsFormHandler, formHandlerScript } from "./lib/client/scripts/formHandler";
49
-
52
+ import { collectAllMappingClasses } from './lib/server/astro/cssCollector';
53
+ import { buildImageMetadataMap, RESPONSIVE_WIDTHS } from './lib/server/ssr/imageMetadata';
54
+ import { needsFormHandler, formHandlerScript } from './lib/client/scripts/formHandler';
50
55
 
51
56
  // ---------------------------------------------------------------------------
52
57
  // Helpers
@@ -70,11 +75,7 @@ function writePageScript(javascript: string | undefined, scriptsDir: string): st
70
75
  return [`/_scripts/${scriptFile}`];
71
76
  }
72
77
 
73
- function copyDirectory(
74
- src: string,
75
- dest: string,
76
- filter?: (filename: string) => boolean,
77
- ): void {
78
+ function copyDirectory(src: string, dest: string, filter?: (filename: string) => boolean): void {
78
79
  if (!existsSync(src)) return;
79
80
  if (!existsSync(dest)) mkdirSync(dest, { recursive: true });
80
81
  const files = readdirSync(src);
@@ -91,9 +92,7 @@ function copyDirectory(
91
92
  // Astro's <Picture> re-derives responsive variants from originals at build
92
93
  // time, so the pre-baked -{width}.webp/.avif files and the SSR-only
93
94
  // manifest.json are dead weight in the exported project.
94
- const imageVariantSuffixRe = new RegExp(
95
- `-(${RESPONSIVE_WIDTHS.join('|')})\\.(webp|avif)$`,
96
- );
95
+ const imageVariantSuffixRe = new RegExp(`-(${RESPONSIVE_WIDTHS.join('|')})\\.(webp|avif)$`);
97
96
  function shouldCopyImageForAstro(filename: string): boolean {
98
97
  if (filename === 'manifest.json') return false;
99
98
  if (imageVariantSuffixRe.test(filename)) return false;
@@ -112,7 +111,7 @@ function buildCMSItemPath(
112
111
  item: CMSItem,
113
112
  slugField: string,
114
113
  locale: string,
115
- i18nConfig: I18nConfig
114
+ i18nConfig: I18nConfig,
116
115
  ): string {
117
116
  let slug = item[slugField] ?? item._slug ?? item._id;
118
117
  if (isI18nValue(slug)) {
@@ -160,10 +159,7 @@ function escapeTemplateLiteral(s: string): string {
160
159
  * Compute locale → URL path map for a page's slug translations.
161
160
  * Used by locale list rendering to generate correct links.
162
161
  */
163
- function computePageSlugMap(
164
- slugs: Record<string, string>,
165
- i18nConfig: I18nConfig
166
- ): Record<string, string> {
162
+ function computePageSlugMap(slugs: Record<string, string>, i18nConfig: I18nConfig): Record<string, string> {
167
163
  const map: Record<string, string> = {};
168
164
  for (const localeConfig of i18nConfig.locales) {
169
165
  const code = localeConfig.code;
@@ -198,7 +194,7 @@ function cmsFieldToZod(field: CMSFieldDefinition): string {
198
194
  return 'z.coerce.date()';
199
195
  case 'select':
200
196
  if (field.options && field.options.length > 0) {
201
- const opts = field.options.map(o => `'${o.replace(/'/g, "\\'")}'`).join(', ');
197
+ const opts = field.options.map((o) => `'${o.replace(/'/g, "\\'")}'`).join(', ');
202
198
  return `z.enum([${opts}])`;
203
199
  }
204
200
  return 'z.string()';
@@ -263,9 +259,7 @@ function collectComponentRefs(node: unknown, acc: Set<string>): void {
263
259
  * structure (it must forward the `cms` prop down). Astro components have
264
260
  * isolated scopes, so each consumer needs the entry threaded in explicitly.
265
261
  */
266
- function computeCmsConsumerComponents(
267
- components: Record<string, ComponentDefinition>
268
- ): Set<string> {
262
+ function computeCmsConsumerComponents(components: Record<string, ComponentDefinition>): Set<string> {
269
263
  const consumers = new Set<string>();
270
264
  const refsByComponent = new Map<string, Set<string>>();
271
265
 
@@ -286,7 +280,11 @@ function computeCmsConsumerComponents(
286
280
  for (const [name, refs] of refsByComponent) {
287
281
  if (consumers.has(name)) continue;
288
282
  for (const ref of refs) {
289
- if (consumers.has(ref)) { consumers.add(name); changed = true; break; }
283
+ if (consumers.has(ref)) {
284
+ consumers.add(name);
285
+ changed = true;
286
+ break;
287
+ }
290
288
  }
291
289
  }
292
290
  }
@@ -359,15 +357,13 @@ function buildSSRFallbackPage(
359
357
  fontPreloads: string,
360
358
  libraryTags: { headCSS?: string; headJS?: string; bodyEndJS?: string },
361
359
  defaultTheme: string,
362
- scriptPaths: string[]
360
+ scriptPaths: string[],
363
361
  ): string {
364
362
  const escapedMeta = escapeTemplateLiteral(result.meta);
365
363
  const escapedHTML = escapeTemplateLiteral(result.html);
366
364
  const escapedFontPreloads = escapeTemplateLiteral(fontPreloads);
367
365
 
368
- const scriptsArrayLiteral = scriptPaths.length > 0
369
- ? `[${scriptPaths.map(s => `"${s}"`).join(', ')}]`
370
- : '[]';
366
+ const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(', ')}]` : '[]';
371
367
 
372
368
  const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral(libraryTags.headCSS || '')}\`, headJS: \`${escapeTemplateLiteral(libraryTags.headJS || '')}\`, bodyEndJS: \`${escapeTemplateLiteral(libraryTags.bodyEndJS || '')}\` }`;
373
369
 
@@ -392,10 +388,7 @@ import BaseLayout from '${importPath}';
392
388
  // Main export
393
389
  // ---------------------------------------------------------------------------
394
390
 
395
- export async function buildAstroProject(
396
- projectRoot?: string,
397
- outputDir?: string
398
- ): Promise<AstroBuildStats> {
391
+ export async function buildAstroProject(projectRoot?: string, outputDir?: string): Promise<AstroBuildStats> {
399
392
  // ----------------------------------------------------------
400
393
  // 1. Setup: load project configuration
401
394
  // ----------------------------------------------------------
@@ -410,7 +403,9 @@ export async function buildAstroProject(
410
403
 
411
404
  const { components, warnings, errors: compErrors } = await loadComponentDirectory(projectPaths.components());
412
405
  const globalComponents: Record<string, ComponentDefinition> = {};
413
- components.forEach((value, key) => { globalComponents[key] = value; });
406
+ components.forEach((value, key) => {
407
+ globalComponents[key] = value;
408
+ });
414
409
  for (const w of warnings) console.warn(` Warning: ${w}`);
415
410
  for (const e of compErrors) console.error(` Error: ${e}`);
416
411
 
@@ -481,7 +476,9 @@ export async function buildAstroProject(
481
476
  const pageId = basePath === '/' ? 'index' : basePath.substring(1);
482
477
  slugMappings.push({ pageId, slugs: pageData.meta.slugs });
483
478
  }
484
- } catch { /* ignore parse errors in first pass */ }
479
+ } catch {
480
+ /* ignore parse errors in first pass */
481
+ }
485
482
  }
486
483
 
487
484
  // ----------------------------------------------------------
@@ -505,13 +502,25 @@ export async function buildAstroProject(
505
502
 
506
503
  // Helper to process a render result
507
504
  function processRenderResult(
508
- result: { html: string; meta: string; title: string; javascript: string; componentCSS?: string; locale: string; interactiveStylesMap: Map<string, InteractiveStyles>; preloadImages: any[]; neededCollections: Set<string>; ssrFallbackCollector?: Map<string, string>; processedRawHtmlCollector?: Map<string, string> },
505
+ result: {
506
+ html: string;
507
+ meta: string;
508
+ title: string;
509
+ javascript: string;
510
+ componentCSS?: string;
511
+ locale: string;
512
+ interactiveStylesMap: Map<string, InteractiveStyles>;
513
+ preloadImages: any[];
514
+ neededCollections: Set<string>;
515
+ ssrFallbackCollector?: Map<string, string>;
516
+ processedRawHtmlCollector?: Map<string, string>;
517
+ },
509
518
  urlPath: string,
510
519
  astroFilePath: string,
511
520
  fileDepth: number,
512
521
  pageData?: JSONPage,
513
522
  pageName?: string,
514
- isCMSPage?: boolean
523
+ isCMSPage?: boolean,
515
524
  ): void {
516
525
  // Collect interactive styles
517
526
  mergeInteractiveStyles(result.interactiveStylesMap);
@@ -596,8 +605,12 @@ export async function buildAstroProject(
596
605
  }
597
606
 
598
607
  const urlPath = isDefault
599
- ? (slug === '' ? '/' : `/${slug}`)
600
- : (slug === '' ? `/${locale}` : `/${locale}/${slug}`);
608
+ ? slug === ''
609
+ ? '/'
610
+ : `/${slug}`
611
+ : slug === ''
612
+ ? `/${locale}`
613
+ : `/${locale}/${slug}`;
601
614
 
602
615
  // Determine .astro file path relative to src/pages/
603
616
  const astroFileName = slug === '' ? 'index.astro' : `${slug}.astro`;
@@ -614,7 +627,7 @@ export async function buildAstroProject(
614
627
  slugMappings,
615
628
  undefined, // cmsContext
616
629
  cmsService,
617
- true // isProductionBuild
630
+ true, // isProductionBuild
618
631
  );
619
632
 
620
633
  processRenderResult(result, urlPath, astroFilePath, fileDepth, pageData, pageName, false);
@@ -708,12 +721,14 @@ export async function buildAstroProject(
708
721
  for (const [fn, fd] of Object.entries(schema.fields || {})) {
709
722
  if (fd.type === 'rich-text') mergedRichTextFields.add(fn);
710
723
  }
711
- } catch { /* ignore parse errors; handled in main loop */ }
724
+ } catch {
725
+ /* ignore parse errors; handled in main loop */
726
+ }
712
727
  }
713
728
  }
714
729
 
715
730
  if (existsSync(templatesDir)) {
716
- const templateFiles = readdirSync(templatesDir).filter(f => f.endsWith('.json'));
731
+ const templateFiles = readdirSync(templatesDir).filter((f) => f.endsWith('.json'));
717
732
 
718
733
  for (const file of templateFiles) {
719
734
  const templateContent = await loadJSONFile(join(templatesDir, file));
@@ -753,7 +768,7 @@ export async function buildAstroProject(
753
768
  slugMappings,
754
769
  undefined, // no CMS context - just collecting metadata
755
770
  cmsService,
756
- true
771
+ true,
757
772
  );
758
773
 
759
774
  // Collect interactive styles and component CSS
@@ -791,13 +806,9 @@ export async function buildAstroProject(
791
806
  // Route file path: blog/[slug].astro for default, pl/blog/[slug].astro for non-default
792
807
  let astroFilePath: string;
793
808
  if (pathPrefix) {
794
- astroFilePath = isDefault
795
- ? `${pathPrefix}[slug].astro`
796
- : `${localeCode}/${pathPrefix}[slug].astro`;
809
+ astroFilePath = isDefault ? `${pathPrefix}[slug].astro` : `${localeCode}/${pathPrefix}[slug].astro`;
797
810
  } else {
798
- astroFilePath = isDefault
799
- ? '[slug].astro'
800
- : `${localeCode}/[slug].astro`;
811
+ astroFilePath = isDefault ? '[slug].astro' : `${localeCode}/[slug].astro`;
801
812
  }
802
813
 
803
814
  const fileDepth = astroFilePath.split('/').length - 1;
@@ -870,9 +881,7 @@ export async function buildAstroProject(
870
881
  }`;
871
882
 
872
883
  const safelistClasses = Array.from(mappingClasses);
873
- const safelistDirectives = safelistClasses
874
- .map(c => `@source inline("${c}");`)
875
- .join('\n');
884
+ const safelistDirectives = safelistClasses.map((c) => `@source inline("${c}");`).join('\n');
876
885
  const tailwindDirectives = safelistDirectives
877
886
  ? `@import "tailwindcss";\n\n${safelistDirectives}`
878
887
  : `@import "tailwindcss";`;
@@ -888,19 +897,14 @@ export async function buildAstroProject(
888
897
  // ----------------------------------------------------------
889
898
  // Escape for embedding inside Astro <Fragment set:html={`...`}> template
890
899
  // literals in the generated BaseLayout file.
891
- const escForTemplateLiteral = (s: string) => s
892
- .replace(/\\/g, '\\\\')
893
- .replace(/`/g, '\\`')
894
- .replace(/\$\{/g, '\\${');
900
+ const escForTemplateLiteral = (s: string) => s.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
895
901
 
896
902
  const customHeadLiteral = escForTemplateLiteral(customCode.head || '');
897
903
  const customBodyStartLiteral = escForTemplateLiteral(customCode.bodyStart || '');
898
904
  const customBodyEndLiteral = escForTemplateLiteral(customCode.bodyEnd || '');
899
905
  const iconTagsLiteral = escForTemplateLiteral(iconTagsHtml);
900
906
 
901
- const formHandlerBlock = projectNeedsFormHandler
902
- ? `\n <script is:inline>\n${formHandlerScript}\n </script>`
903
- : '';
907
+ const formHandlerBlock = projectNeedsFormHandler ? `\n <script is:inline>\n${formHandlerScript}\n </script>` : '';
904
908
 
905
909
  const baseLayoutContent = `---
906
910
  import '../styles/global.css';
@@ -954,11 +958,20 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
954
958
  let componentFileCount = 0;
955
959
  for (const [compName, compDef] of Object.entries(emittableComponents)) {
956
960
  try {
957
- const astroContent = emitAstroComponent(compName, compDef, emittableComponents, breakpoints, i18nConfig.defaultLocale, responsiveScales, remConversionConfig, {
958
- cmsConsumers: cmsConsumerComponents,
959
- cmsRichTextFields: mergedRichTextFields,
960
- collectionUrlExpr,
961
- });
961
+ const astroContent = emitAstroComponent(
962
+ compName,
963
+ compDef,
964
+ emittableComponents,
965
+ breakpoints,
966
+ i18nConfig.defaultLocale,
967
+ responsiveScales,
968
+ remConversionConfig,
969
+ {
970
+ cmsConsumers: cmsConsumerComponents,
971
+ cmsRichTextFields: mergedRichTextFields,
972
+ collectionUrlExpr,
973
+ },
974
+ );
962
975
  await writeFile(join(componentsOutDir, `${compName}.astro`), astroContent, 'utf-8');
963
976
  componentFileCount++;
964
977
  } catch (error: any) {
@@ -983,10 +996,9 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
983
996
  const ssrFallbacks = result.ssrFallbackCollector ?? new Map<string, string>();
984
997
 
985
998
  // Compute slug map for locale list rendering
986
- const pageSlugMap: Record<string, string> | undefined =
987
- result.pageData.meta?.slugs
988
- ? computePageSlugMap(result.pageData.meta.slugs, i18nConfig)
989
- : undefined;
999
+ const pageSlugMap: Record<string, string> | undefined = result.pageData.meta?.slugs
1000
+ ? computePageSlugMap(result.pageData.meta.slugs, i18nConfig)
1001
+ : undefined;
990
1002
 
991
1003
  // Component-structured pages don't need page-level _scripts/*.js
992
1004
  // because each .astro component already has its own inline <script>
@@ -1016,7 +1028,9 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
1016
1028
  });
1017
1029
  } catch (error: any) {
1018
1030
  // Fallback to SSR HTML if component emission fails — needs page-level script
1019
- console.warn(` Warning: component emission failed for ${result.urlPath}, using SSR fallback: ${error?.message}`);
1031
+ console.warn(
1032
+ ` Warning: component emission failed for ${result.urlPath}, using SSR fallback: ${error?.message}`,
1033
+ );
1020
1034
  scriptPaths = writePageScript(result.javascript, scriptsDir);
1021
1035
  astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
1022
1036
  }
@@ -1084,8 +1098,8 @@ export const GET: APIRoute = () => {
1084
1098
  // Skip `*.draft.json` siblings in production builds — they mirror the
1085
1099
  // published item-list filter and may hold partial/invalid WIP data.
1086
1100
  const isDevBuild = process.env.MENO_DEV_BUILD === 'true';
1087
- const itemFiles = readdirSync(cmsItemsDir).filter(f =>
1088
- f.endsWith('.json') && (isDevBuild || !f.endsWith(`${CMS_DRAFT_SUFFIX}.json`))
1101
+ const itemFiles = readdirSync(cmsItemsDir).filter(
1102
+ (f) => f.endsWith('.json') && (isDevBuild || !f.endsWith(`${CMS_DRAFT_SUFFIX}.json`)),
1089
1103
  );
1090
1104
 
1091
1105
  for (const itemFile of itemFiles) {
@@ -1102,11 +1116,7 @@ export const GET: APIRoute = () => {
1102
1116
  resolved[fieldName] = serializeRichTextValue(resolved[fieldName]);
1103
1117
  }
1104
1118
 
1105
- await writeFile(
1106
- join(collectionDir, itemFile),
1107
- JSON.stringify(resolved, null, 2),
1108
- 'utf-8'
1109
- );
1119
+ await writeFile(join(collectionDir, itemFile), JSON.stringify(resolved, null, 2), 'utf-8');
1110
1120
  } catch (err: any) {
1111
1121
  console.warn(` Warning: could not process CMS item ${itemFile}: ${err?.message}`);
1112
1122
  }
@@ -1173,7 +1183,7 @@ export { collections };
1173
1183
  const srcAssetDir = join(projectPaths.project, dir);
1174
1184
  if (existsSync(srcAssetDir)) {
1175
1185
  copyDirectory(srcAssetDir, join(publicDir, dir));
1176
- }
1186
+ }
1177
1187
  }
1178
1188
 
1179
1189
  // Copy libraries folder if it exists
@@ -1212,20 +1222,21 @@ export { collections };
1212
1222
  dependencies: {
1213
1223
  // Astro 5 (stable Vite), NOT 6 — Astro 6's rolldown-vite breaks
1214
1224
  // @tailwindcss/vite at build time ("Missing field `tsconfigPaths`").
1215
- 'astro': '^5.0.0',
1225
+ astro: '^5.0.0',
1216
1226
  '@astrojs/sitemap': '^3.0.0',
1217
1227
  '@tailwindcss/vite': '^4.0.0',
1218
- 'tailwindcss': '^4.0.0',
1228
+ tailwindcss: '^4.0.0',
1219
1229
  },
1220
1230
  };
1221
1231
 
1222
1232
  await writeFile(join(outDir, 'package.json'), JSON.stringify(packageJson, null, 2), 'utf-8');
1223
1233
 
1224
1234
  // astro.config.mjs
1225
- const localeCodes = i18nConfig.locales.map(l => l.code);
1226
- const i18nBlock = i18nConfig.locales.length > 1
1227
- ? `\n i18n: {\n defaultLocale: '${i18nConfig.defaultLocale}',\n locales: [${localeCodes.map(c => `'${c}'`).join(', ')}],\n routing: { prefixDefaultLocale: false },\n },`
1228
- : '';
1235
+ const localeCodes = i18nConfig.locales.map((l) => l.code);
1236
+ const i18nBlock =
1237
+ i18nConfig.locales.length > 1
1238
+ ? `\n i18n: {\n defaultLocale: '${i18nConfig.defaultLocale}',\n locales: [${localeCodes.map((c) => `'${c}'`).join(', ')}],\n routing: { prefixDefaultLocale: false },\n },`
1239
+ : '';
1229
1240
 
1230
1241
  const astroConfig = `import { defineConfig } from 'astro/config';
1231
1242
  import tailwindcss from '@tailwindcss/vite';
@@ -1252,7 +1263,13 @@ export default defineConfig({${siteUrl ? `\n site: '${siteUrl}',` : ''}${i18nBl
1252
1263
  // box. `astro` is a real dependency here (see package.json above), so once
1253
1264
  // Netlify runs `npm install`, `astro build` is on PATH and writes to dist/.
1254
1265
  // Harmless on other hosts (Cloudflare Pages / Vercel ignore this file).
1255
- const netlifyToml = `# Generated by Meno's Astro build.
1266
+ //
1267
+ // Multi-locale projects WITH a 404 page (pages/404.json) also get the managed
1268
+ // locale-404 redirects block (lib/shared/netlifyLocale404.ts): the regular-pages
1269
+ // loop above emits src/pages/<locale>/404.astro per non-default locale, which
1270
+ // Astro builds to dist/<locale>/404/index.html — exactly the rules' rewrite
1271
+ // target — while the root 404.astro becomes Netlify's default catch-all 404.html.
1272
+ const baseNetlifyToml = `# Generated by Meno's Astro build.
1256
1273
  [build]
1257
1274
  command = "npm run build"
1258
1275
  publish = "dist"
@@ -1260,6 +1277,7 @@ export default defineConfig({${siteUrl ? `\n site: '${siteUrl}',` : ''}${i18nBl
1260
1277
  [build.environment]
1261
1278
  NODE_VERSION = "22"
1262
1279
  `;
1280
+ const netlifyToml = syncNetlifyLocale404Block(baseNetlifyToml, i18nConfig, pageFiles.includes('404.json'));
1263
1281
  await writeFile(join(outDir, 'netlify.toml'), netlifyToml, 'utf-8');
1264
1282
 
1265
1283
  // src/env.d.ts — resolves astro:assets and other virtual module types in IDE