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
@@ -53,7 +53,12 @@ import {
53
53
  MENO_BIND_SENTINEL_EXACT_RE,
54
54
  } from './types';
55
55
  import { mapStylesToWebflow, buildInstanceStyleCombo } from './styleMapper';
56
- import { processCodeTemplates, hasTemplates as hasCodeTemplates, resolveHtmlMapping, isHtmlMapping } from '../../client/templateEngine';
56
+ import {
57
+ processCodeTemplates,
58
+ hasTemplates as hasCodeTemplates,
59
+ resolveHtmlMapping,
60
+ isHtmlMapping,
61
+ } from '../../client/templateEngine';
57
62
  import { resolvePropsFromDefinition } from '../../shared/propResolver';
58
63
  import { readFile } from 'fs/promises';
59
64
  import { join, basename, extname } from 'path';
@@ -253,7 +258,11 @@ function themedClassSuffix(ctx: WebflowEmitContext): string {
253
258
  const t = ctx.currentTheme;
254
259
  if (!t) return '';
255
260
  if (ctx.defaultTheme && t === ctx.defaultTheme) return '';
256
- const safe = t.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
261
+ const safe = t
262
+ .toLowerCase()
263
+ .replace(/[^a-z0-9-]/g, '-')
264
+ .replace(/-+/g, '-')
265
+ .replace(/^-|-$/g, '');
257
266
  if (!safe) return '';
258
267
  return `-theme-${safe}`;
259
268
  }
@@ -295,7 +304,7 @@ function mintInstanceComboName(ctx: WebflowEmitContext, identity: string): strin
295
304
  * skip default-baking entirely).
296
305
  */
297
306
  function extractInterfaceDefaults(
298
- iface: Record<string, { default?: unknown }> | undefined
307
+ iface: Record<string, { default?: unknown }> | undefined,
299
308
  ): Record<string, unknown> | undefined {
300
309
  if (!iface) return undefined;
301
310
  const out: Record<string, unknown> = {};
@@ -316,10 +325,7 @@ function extractInterfaceDefaults(
316
325
  * Page-level walks (no enclosing component) still get a usable context — we
317
326
  * just won't have `instanceProps` to layer on top.
318
327
  */
319
- function buildTemplateProps(
320
- ctx: WebflowEmitContext,
321
- instanceProps?: Record<string, unknown>
322
- ): Record<string, unknown> {
328
+ function buildTemplateProps(ctx: WebflowEmitContext, instanceProps?: Record<string, unknown>): Record<string, unknown> {
323
329
  return {
324
330
  ...(ctx.templateContext ?? {}),
325
331
  ...(ctx.cmsContext ?? {}),
@@ -336,16 +342,10 @@ function buildTemplateProps(
336
342
  * `RAW_HTML_PREFIX`-marked rich-text values get flattened to visible text after
337
343
  * substitution so the sentinel + inline HTML can't leak into a tag/attribute.
338
344
  */
339
- function resolveStringTemplate(
340
- text: string,
341
- ctx: WebflowEmitContext,
342
- instanceProps?: Record<string, unknown>
343
- ): string {
345
+ function resolveStringTemplate(text: string, ctx: WebflowEmitContext, instanceProps?: Record<string, unknown>): string {
344
346
  if (!hasCodeTemplates(text)) return text;
345
347
  const out = processCodeTemplates(text, buildTemplateProps(ctx, instanceProps));
346
- return out.startsWith(RAW_HTML_PREFIX)
347
- ? flattenInlineHtmlToText(out.slice(RAW_HTML_PREFIX.length))
348
- : out;
348
+ return out.startsWith(RAW_HTML_PREFIX) ? flattenInlineHtmlToText(out.slice(RAW_HTML_PREFIX.length)) : out;
349
349
  }
350
350
 
351
351
  const HEADING_TAGS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']);
@@ -428,11 +428,7 @@ function applyLinkTextDecorationDefault(cls: WebflowStyleClass): void {
428
428
  * across re-imports and is unique to this exact body root (the outer combo
429
429
  * name is keyed by the instance's outer location).
430
430
  */
431
- function mergeComboClasses(
432
- inner: WebflowStyleClass,
433
- outer: WebflowStyleClass,
434
- parentName: string,
435
- ): WebflowStyleClass {
431
+ function mergeComboClasses(inner: WebflowStyleClass, outer: WebflowStyleClass, parentName: string): WebflowStyleClass {
436
432
  const innerSuffix = inner.name.startsWith('is-') ? inner.name.slice(3) : inner.name;
437
433
  const merged: WebflowStyleClass = {
438
434
  name: `${outer.name}_${innerSuffix}`,
@@ -528,9 +524,14 @@ async function maybeInlineLocalImage(element: WebflowElement, src: string): Prom
528
524
  * are decoded; comments are stripped.
529
525
  */
530
526
  function flattenInlineHtmlToText(raw: string): string {
531
- const decode = (s: string) => s
532
- .replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>')
533
- .replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&nbsp;/g, ' ');
527
+ const decode = (s: string) =>
528
+ s
529
+ .replace(/&amp;/g, '&')
530
+ .replace(/&lt;/g, '<')
531
+ .replace(/&gt;/g, '>')
532
+ .replace(/&quot;/g, '"')
533
+ .replace(/&#39;/g, "'")
534
+ .replace(/&nbsp;/g, ' ');
534
535
 
535
536
  let out = '';
536
537
  const tagRe = /<!--[\s\S]*?-->|<\/?([a-zA-Z][a-zA-Z0-9]*)[^>]*>/g;
@@ -562,11 +563,7 @@ function flattenInlineHtmlToText(raw: string): string {
562
563
  * breakpoint parameter lets us materialize the same `var(--h1-fs)` reference
563
564
  * to its scaled value at every Meno breakpoint.
564
565
  */
565
- function resolveVarsInValue(
566
- value: string,
567
- ctx: WebflowEmitContext,
568
- breakpoint: string = 'base'
569
- ): string {
566
+ function resolveVarsInValue(value: string, ctx: WebflowEmitContext, breakpoint: string = 'base'): string {
570
567
  if (!value || (!ctx.themeVars && !ctx.projectVars)) return value;
571
568
  // If `currentTheme` names a theme that doesn't exist in this project's
572
569
  // colors.json, fall back to the project default — that mirrors runtime
@@ -575,14 +572,10 @@ function resolveVarsInValue(
575
572
  // would survive the substitution pass and ship as literal `var(--…)` to
576
573
  // Webflow.
577
574
  const themeMap = ctx.themeVars
578
- ? (
579
- (ctx.currentTheme && ctx.themeVars[ctx.currentTheme])
580
- ?? (ctx.defaultTheme ? ctx.themeVars[ctx.defaultTheme] : undefined)
581
- )
582
- : undefined;
583
- const projectMap = ctx.projectVars
584
- ? (ctx.projectVars[breakpoint] || ctx.projectVars.base)
575
+ ? ((ctx.currentTheme && ctx.themeVars[ctx.currentTheme]) ??
576
+ (ctx.defaultTheme ? ctx.themeVars[ctx.defaultTheme] : undefined))
585
577
  : undefined;
578
+ const projectMap = ctx.projectVars ? ctx.projectVars[breakpoint] || ctx.projectVars.base : undefined;
586
579
  const pattern = /var\(\s*(--[\w-]+)\s*(?:,\s*([^)]+))?\)/g;
587
580
 
588
581
  let current = value;
@@ -608,7 +601,7 @@ function resolveVarsInValue(
608
601
  function substituteVarsInStyleObject(
609
602
  style: StyleObject,
610
603
  ctx: WebflowEmitContext,
611
- breakpoint: string = 'base'
604
+ breakpoint: string = 'base',
612
605
  ): StyleObject {
613
606
  const out: StyleObject = {};
614
607
  for (const [k, v] of Object.entries(style)) {
@@ -637,7 +630,7 @@ function projectBreakpointNames(ctx: WebflowEmitContext): string[] {
637
630
  function expandResponsiveVarsInto(
638
631
  baseStyle: StyleObject,
639
632
  responsive: ResponsiveStyleObject,
640
- ctx: WebflowEmitContext
633
+ ctx: WebflowEmitContext,
641
634
  ): void {
642
635
  if (!ctx.projectVars) return;
643
636
  const bps = projectBreakpointNames(ctx);
@@ -673,7 +666,7 @@ function expandResponsiveVarsInto(
673
666
  */
674
667
  function substituteVarsInStyle(
675
668
  style: StyleObject | ResponsiveStyleObject | undefined,
676
- ctx: WebflowEmitContext
669
+ ctx: WebflowEmitContext,
677
670
  ): StyleObject | ResponsiveStyleObject | undefined {
678
671
  if (!style) return style;
679
672
  if (isResponsiveStyleObject(style)) {
@@ -700,13 +693,16 @@ function substituteVarsInStyle(
700
693
 
701
694
  function substituteVarsInInteractive(
702
695
  rules: InteractiveStyles | undefined,
703
- ctx: WebflowEmitContext
696
+ ctx: WebflowEmitContext,
704
697
  ): InteractiveStyles | undefined {
705
698
  if (!rules) return rules;
706
- return rules.map((rule): InteractiveStyleRule => ({
707
- ...rule,
708
- style: (substituteVarsInStyle(rule.style as StyleObject | ResponsiveStyleObject, ctx) ?? rule.style) as StyleValue,
709
- }));
699
+ return rules.map(
700
+ (rule): InteractiveStyleRule => ({
701
+ ...rule,
702
+ style: (substituteVarsInStyle(rule.style as StyleObject | ResponsiveStyleObject, ctx) ??
703
+ rule.style) as StyleValue,
704
+ }),
705
+ );
710
706
  }
711
707
 
712
708
  /**
@@ -769,10 +765,7 @@ function substituteVarsInStyleClass(cls: WebflowStyleClass, ctx: WebflowEmitCont
769
765
  * Kept private so we don't widen styleMapper's public surface just for the
770
766
  * combo-class expansion above.
771
767
  */
772
- function menoBreakpointToWebflowTier(
773
- bpName: string,
774
- breakpoints: BreakpointConfig
775
- ): string {
768
+ function menoBreakpointToWebflowTier(bpName: string, breakpoints: BreakpointConfig): string {
776
769
  if (bpName === 'tablet') return 'medium';
777
770
  if (bpName === 'mobile') return 'small';
778
771
  const entry = breakpoints[bpName];
@@ -810,7 +803,7 @@ function isResponsiveStyleObject(style: StyleObject | ResponsiveStyleObject): st
810
803
  function extractBaseColor(
811
804
  style: StyleObject | ResponsiveStyleObject | undefined,
812
805
  ctx?: WebflowEmitContext,
813
- instanceProps?: Record<string, unknown>
806
+ instanceProps?: Record<string, unknown>,
814
807
  ): string | undefined {
815
808
  if (!style) return undefined;
816
809
  const flat: StyleObject | undefined = isResponsiveStyleObject(style)
@@ -860,10 +853,7 @@ function inlineCurrentColorInSvg(svg: string, color: string): string {
860
853
  * styleMapper can still emit them as Webflow combo classes. Values without
861
854
  * templates pass through unchanged.
862
855
  */
863
- function resolveTemplatesInStyleObject(
864
- style: StyleObject,
865
- props: Record<string, unknown>
866
- ): StyleObject {
856
+ function resolveTemplatesInStyleObject(style: StyleObject, props: Record<string, unknown>): StyleObject {
867
857
  const result: StyleObject = {};
868
858
  for (const [key, value] of Object.entries(style)) {
869
859
  if (typeof value === 'string' && hasCodeTemplates(value)) {
@@ -882,7 +872,7 @@ function resolveTemplatesInStyleObject(
882
872
  */
883
873
  function resolveStyleTemplates(
884
874
  style: StyleObject | ResponsiveStyleObject | undefined,
885
- props: Record<string, unknown> | undefined
875
+ props: Record<string, unknown> | undefined,
886
876
  ): StyleObject | ResponsiveStyleObject | undefined {
887
877
  if (!style || !props) return style;
888
878
  if (isResponsiveStyleObject(style)) {
@@ -927,7 +917,7 @@ function extractSingleTemplateProp(value: string): { prop: string; prefix: strin
927
917
  function templatesToSyntheticMappings(
928
918
  style: StyleObject,
929
919
  componentDefaults: Record<string, unknown>,
930
- instanceProps: Record<string, unknown>
920
+ instanceProps: Record<string, unknown>,
931
921
  ): StyleObject {
932
922
  const out: StyleObject = {};
933
923
  for (const [key, value] of Object.entries(style)) {
@@ -973,7 +963,7 @@ function templatesToSyntheticMappings(
973
963
  function convertStyleTemplatesToMappings(
974
964
  style: StyleObject | ResponsiveStyleObject | undefined,
975
965
  componentDefaults: Record<string, unknown> | undefined,
976
- instanceProps: Record<string, unknown> | undefined
966
+ instanceProps: Record<string, unknown> | undefined,
977
967
  ): StyleObject | ResponsiveStyleObject | undefined {
978
968
  if (!style || !componentDefaults || !instanceProps) return style;
979
969
  if (isResponsiveStyleObject(style)) {
@@ -995,10 +985,7 @@ function convertStyleTemplatesToMappings(
995
985
  * context is available to decide, default to rendering (true) so we don't drop
996
986
  * nodes that would otherwise be shown.
997
987
  */
998
- function shouldRenderNode(
999
- node: ComponentNode,
1000
- instanceProps?: Record<string, unknown>
1001
- ): boolean {
988
+ function shouldRenderNode(node: ComponentNode, instanceProps?: Record<string, unknown>): boolean {
1002
989
  if (!hasIf(node)) return true;
1003
990
  const ifValue = node.if;
1004
991
 
@@ -1014,12 +1001,7 @@ function shouldRenderNode(
1014
1001
  if (typeof ifValue === 'string') {
1015
1002
  if (!instanceProps) return true;
1016
1003
  const resolved = processCodeTemplates(ifValue, instanceProps);
1017
- return (
1018
- Boolean(resolved) &&
1019
- resolved !== 'false' &&
1020
- resolved !== '0' &&
1021
- resolved !== ''
1022
- );
1004
+ return Boolean(resolved) && resolved !== 'false' && resolved !== '0' && resolved !== '';
1023
1005
  }
1024
1006
 
1025
1007
  return true;
@@ -1030,13 +1012,16 @@ function shouldRenderNode(
1030
1012
  */
1031
1013
  function resolveInteractiveStyleTemplates(
1032
1014
  rules: InteractiveStyles | undefined,
1033
- props: Record<string, unknown> | undefined
1015
+ props: Record<string, unknown> | undefined,
1034
1016
  ): InteractiveStyles | undefined {
1035
1017
  if (!rules || !props) return rules;
1036
- return rules.map((rule): InteractiveStyleRule => ({
1037
- ...rule,
1038
- style: (resolveStyleTemplates(rule.style as StyleObject | ResponsiveStyleObject, props) ?? rule.style) as StyleValue,
1039
- }));
1018
+ return rules.map(
1019
+ (rule): InteractiveStyleRule => ({
1020
+ ...rule,
1021
+ style: (resolveStyleTemplates(rule.style as StyleObject | ResponsiveStyleObject, props) ??
1022
+ rule.style) as StyleValue,
1023
+ }),
1024
+ );
1040
1025
  }
1041
1026
 
1042
1027
  // ---------------------------------------------------------------------------
@@ -1053,7 +1038,7 @@ function resolveInteractiveStyleTemplates(
1053
1038
  export async function nodeToWebflow(
1054
1039
  node: ComponentNode | ComponentNode[] | string | number | null | undefined,
1055
1040
  ctx: WebflowEmitContext,
1056
- instanceProps?: Record<string, unknown>
1041
+ instanceProps?: Record<string, unknown>,
1057
1042
  ): Promise<WebflowElement[]> {
1058
1043
  if (node === null || node === undefined) return [];
1059
1044
 
@@ -1115,7 +1100,7 @@ export async function nodeToWebflow(
1115
1100
  async function emitHtmlNode(
1116
1101
  node: HtmlNode,
1117
1102
  ctx: WebflowEmitContext,
1118
- instanceProps?: Record<string, unknown>
1103
+ instanceProps?: Record<string, unknown>,
1119
1104
  ): Promise<WebflowElement> {
1120
1105
  // Resolve `{{...}}` in the tag against the same layered context meno-core
1121
1106
  // walks at runtime — page-level / slot-injected nodes don't have
@@ -1128,15 +1113,14 @@ async function emitHtmlNode(
1128
1113
  const attributes: Record<string, string | number | boolean> = {};
1129
1114
  if (node.attributes) {
1130
1115
  for (const [key, value] of Object.entries(node.attributes)) {
1131
- attributes[key] = (typeof value === 'string')
1132
- ? resolveStringTemplate(value, ctx, instanceProps)
1133
- : value;
1116
+ attributes[key] = typeof value === 'string' ? resolveStringTemplate(value, ctx, instanceProps) : value;
1134
1117
  }
1135
1118
  }
1136
1119
 
1137
- const themedCtx: WebflowEmitContext = typeof attributes.theme === 'string' && attributes.theme
1138
- ? { ...ctx, currentTheme: attributes.theme as string }
1139
- : ctx;
1120
+ const themedCtx: WebflowEmitContext =
1121
+ typeof attributes.theme === 'string' && attributes.theme
1122
+ ? { ...ctx, currentTheme: attributes.theme as string }
1123
+ : ctx;
1140
1124
 
1141
1125
  const rawStyle = node.style as StyleObject | ResponsiveStyleObject | undefined;
1142
1126
  const rawInteractiveStyles = node.interactiveStyles as InteractiveStyles | undefined;
@@ -1144,18 +1128,11 @@ async function emitHtmlNode(
1144
1128
  // StyleMappings before resolution, so values driven by an interface prop
1145
1129
  // emit per-instance combo classes (`is-maxwidth-640px`) instead of
1146
1130
  // collapsing into a single primary class shared by every instance.
1147
- const styleWithMappings = convertStyleTemplatesToMappings(
1148
- rawStyle,
1149
- ctx.componentDefaults,
1150
- instanceProps,
1151
- );
1152
- const style = substituteVarsInStyle(
1153
- resolveStyleTemplates(styleWithMappings, instanceProps),
1154
- themedCtx
1155
- );
1131
+ const styleWithMappings = convertStyleTemplatesToMappings(rawStyle, ctx.componentDefaults, instanceProps);
1132
+ const style = substituteVarsInStyle(resolveStyleTemplates(styleWithMappings, instanceProps), themedCtx);
1156
1133
  const interactiveStyles = substituteVarsInInteractive(
1157
1134
  resolveInteractiveStyleTemplates(rawInteractiveStyles, instanceProps),
1158
- themedCtx
1135
+ themedCtx,
1159
1136
  );
1160
1137
 
1161
1138
  // Generate element class and map styles.
@@ -1170,15 +1147,26 @@ async function emitHtmlNode(
1170
1147
  const isLinkLike = LINK_LIKE_TAGS.has(tagLower);
1171
1148
  const isParagraph = tagLower === 'p';
1172
1149
  const isList = LIST_TAGS.has(tagLower);
1173
- const needsClass = style || (interactiveStyles && interactiveStyles.length > 0) || node.generateElementClass || isHeading || isLinkLike || isParagraph || isList;
1150
+ const needsClass =
1151
+ style ||
1152
+ (interactiveStyles && interactiveStyles.length > 0) ||
1153
+ node.generateElementClass ||
1154
+ isHeading ||
1155
+ isLinkLike ||
1156
+ isParagraph ||
1157
+ isList;
1174
1158
  let className: string | undefined;
1175
1159
  let comboClassNames: string[] | undefined;
1176
1160
 
1177
1161
  if (needsClass) {
1178
1162
  const elementClass = withThemeSuffix(buildElementClass(ctx, node.label), themedCtx);
1179
1163
  const { primaryClass, comboClasses } = mapStylesToWebflow(
1180
- elementClass, style, interactiveStyles, ctx.breakpoints, ctx.responsiveScales,
1181
- { instanceProps, componentDefaults: ctx.componentDefaults, themeSuffix: themedClassSuffix(themedCtx) }
1164
+ elementClass,
1165
+ style,
1166
+ interactiveStyles,
1167
+ ctx.breakpoints,
1168
+ ctx.responsiveScales,
1169
+ { instanceProps, componentDefaults: ctx.componentDefaults, themeSuffix: themedClassSuffix(themedCtx) },
1182
1170
  );
1183
1171
 
1184
1172
  substituteVarsInStyleClass(primaryClass, themedCtx);
@@ -1203,11 +1191,7 @@ async function emitHtmlNode(
1203
1191
  // can later run them through `generateInteractiveCSS` for any rules
1204
1192
  // Webflow's class system can't represent (descendant selectors via
1205
1193
  // `prefix`, class-style postfixes, breakpoint-divided pseudos).
1206
- if (
1207
- ctx.interactiveStylesMap
1208
- && Array.isArray(interactiveStyles)
1209
- && interactiveStyles.length > 0
1210
- ) {
1194
+ if (ctx.interactiveStylesMap && Array.isArray(interactiveStyles) && interactiveStyles.length > 0) {
1211
1195
  ctx.interactiveStylesMap.set(primaryClass.name, interactiveStyles);
1212
1196
  }
1213
1197
  }
@@ -1220,11 +1204,7 @@ async function emitHtmlNode(
1220
1204
  // Optimize: single string child becomes textContent instead of child element
1221
1205
  if (typeof node.children === 'string') {
1222
1206
  textContent = resolveStringTemplate(node.children, ctx, instanceProps);
1223
- } else if (
1224
- Array.isArray(node.children) &&
1225
- node.children.length === 1 &&
1226
- typeof node.children[0] === 'string'
1227
- ) {
1207
+ } else if (Array.isArray(node.children) && node.children.length === 1 && typeof node.children[0] === 'string') {
1228
1208
  const text = node.children[0] as string;
1229
1209
  textContent = resolveStringTemplate(text, ctx, instanceProps);
1230
1210
  } else {
@@ -1270,7 +1250,7 @@ async function emitHtmlNode(
1270
1250
  async function emitComponentInstance(
1271
1251
  node: ComponentInstanceNode,
1272
1252
  ctx: WebflowEmitContext,
1273
- parentProps?: Record<string, unknown>
1253
+ parentProps?: Record<string, unknown>,
1274
1254
  ): Promise<WebflowElement[]> {
1275
1255
  const compDef = ctx.globalComponents[node.component];
1276
1256
  if (!compDef) {
@@ -1293,9 +1273,8 @@ async function emitComponentInstance(
1293
1273
  const parentTemplateProps = parentProps ?? buildTemplateProps(ctx);
1294
1274
  for (const [key, value] of Object.entries(node.props)) {
1295
1275
  if (key === 'children') continue;
1296
- passedProps[key] = (typeof value === 'string' && hasCodeTemplates(value))
1297
- ? processCodeTemplates(value, parentTemplateProps)
1298
- : value;
1276
+ passedProps[key] =
1277
+ typeof value === 'string' && hasCodeTemplates(value) ? processCodeTemplates(value, parentTemplateProps) : value;
1299
1278
  }
1300
1279
  }
1301
1280
 
@@ -1331,17 +1310,11 @@ async function emitComponentInstance(
1331
1310
  // promotion for that instance and fall through to inline expansion so
1332
1311
  // `emitInlineComponentBody` attaches the per-property combos directly.
1333
1312
  const hasInstanceStyleOverrides =
1334
- Boolean(structured?.acceptsStyles)
1335
- && (
1336
- (node.style && Object.keys(node.style as object).length > 0)
1337
- || (Array.isArray(node.interactiveStyles) && node.interactiveStyles.length > 0)
1338
- );
1313
+ Boolean(structured?.acceptsStyles) &&
1314
+ ((node.style && Object.keys(node.style as object).length > 0) ||
1315
+ (Array.isArray(node.interactiveStyles) && node.interactiveStyles.length > 0));
1339
1316
  const promotedNames = ctx.promotedComponentNames || PROMOTED_TO_WEBFLOW_COMPONENT;
1340
- if (
1341
- promotedNames.has(node.component)
1342
- && ctx.promotedComponents
1343
- && !hasInstanceStyleOverrides
1344
- ) {
1317
+ if (promotedNames.has(node.component) && ctx.promotedComponents && !hasInstanceStyleOverrides) {
1345
1318
  const promoted = ctx.promotedComponents;
1346
1319
  if (!promoted.has(node.component)) {
1347
1320
  const defaultProps: Record<string, unknown> = {};
@@ -1408,8 +1381,8 @@ async function emitInlineComponentBody(
1408
1381
  // Container's body fires its own slot, the marker is the only thing
1409
1382
  // available, has no slot context left, and renders nothing.
1410
1383
  let effectiveChildren = node.children;
1411
- let inheritedSlotEmitContext = ctx.slotEmitContext;
1412
- let inheritedSlotInstanceProps: Record<string, unknown> | undefined = undefined;
1384
+ const inheritedSlotEmitContext = ctx.slotEmitContext;
1385
+ let inheritedSlotInstanceProps: Record<string, unknown> | undefined;
1413
1386
  let didForwardSlot = false;
1414
1387
  if (node.children != null && typeof node.children !== 'string') {
1415
1388
  const childArr = Array.isArray(node.children) ? node.children : [node.children];
@@ -1450,13 +1423,14 @@ async function emitInlineComponentBody(
1450
1423
  fileName: node.component,
1451
1424
  elementPath: [0],
1452
1425
  slotChildren: effectiveChildren,
1453
- slotEmitContext: didForwardSlot && inheritedSlotEmitContext
1454
- ? inheritedSlotEmitContext
1455
- : {
1456
- fileType: ctx.fileType,
1457
- fileName: ctx.fileName,
1458
- elementPath: [...ctx.elementPath],
1459
- },
1426
+ slotEmitContext:
1427
+ didForwardSlot && inheritedSlotEmitContext
1428
+ ? inheritedSlotEmitContext
1429
+ : {
1430
+ fileType: ctx.fileType,
1431
+ fileName: ctx.fileName,
1432
+ elementPath: [...ctx.elementPath],
1433
+ },
1460
1434
  // Slot children authored alongside this instance refer to the OUTER
1461
1435
  // component's interface (the one whose body contains `<Component …>{slot
1462
1436
  // children}</Component>`). When the body hits its `<slot/>`, those
@@ -1475,9 +1449,7 @@ async function emitInlineComponentBody(
1475
1449
  // alongside resolved props. resolvedProps wins on key conflicts so
1476
1450
  // explicit instance props still override.
1477
1451
  const ctxTemplate = ctx.templateContext as Record<string, unknown> | undefined;
1478
- const bodyProps = ctxTemplate
1479
- ? { ...ctxTemplate, ...resolvedProps }
1480
- : resolvedProps;
1452
+ const bodyProps = ctxTemplate ? { ...ctxTemplate, ...resolvedProps } : resolvedProps;
1481
1453
  const emitted = await nodeToWebflow(body, compCtx, bodyProps);
1482
1454
 
1483
1455
  // `acceptsStyles`: forward instance-level style / interactiveStyles
@@ -1487,12 +1459,10 @@ async function emitInlineComponentBody(
1487
1459
  // named after the instance's outer location so two instances of the same
1488
1460
  // component on the same page don't share a single class.
1489
1461
  if (
1490
- structured?.acceptsStyles
1491
- && emitted.length > 0
1492
- && (
1493
- (node.style && Object.keys(node.style as object).length > 0)
1494
- || (Array.isArray(node.interactiveStyles) && node.interactiveStyles.length > 0)
1495
- )
1462
+ structured?.acceptsStyles &&
1463
+ emitted.length > 0 &&
1464
+ ((node.style && Object.keys(node.style as object).length > 0) ||
1465
+ (Array.isArray(node.interactiveStyles) && node.interactiveStyles.length > 0))
1496
1466
  ) {
1497
1467
  const root = emitted[0];
1498
1468
  if (root && typeof root === 'object') {
@@ -1508,10 +1478,7 @@ async function emitInlineComponentBody(
1508
1478
 
1509
1479
  const rawStyle = node.style as StyleObject | ResponsiveStyleObject | undefined;
1510
1480
  const rawInteractive = node.interactiveStyles as InteractiveStyles | undefined;
1511
- const resolvedStyle = substituteVarsInStyle(
1512
- resolveStyleTemplates(rawStyle, parentProps),
1513
- ctx,
1514
- );
1481
+ const resolvedStyle = substituteVarsInStyle(resolveStyleTemplates(rawStyle, parentProps), ctx);
1515
1482
  const resolvedInteractive = substituteVarsInInteractive(
1516
1483
  resolveInteractiveStyleTemplates(rawInteractive, parentProps),
1517
1484
  ctx,
@@ -1542,9 +1509,8 @@ async function emitInlineComponentBody(
1542
1509
  // override into a fresh merged class instead of stacking. Outer
1543
1510
  // instance overrides land last so they win on key conflicts,
1544
1511
  // mirroring SSR's merge order in `ssrRenderer.ts:1244`.
1545
- const existingComboName = Array.isArray(root.comboClasses) && root.comboClasses.length > 0
1546
- ? root.comboClasses[0]
1547
- : undefined;
1512
+ const existingComboName =
1513
+ Array.isArray(root.comboClasses) && root.comboClasses.length > 0 ? root.comboClasses[0] : undefined;
1548
1514
  const inner = existingComboName ? ctx.styleClasses.get(existingComboName) : undefined;
1549
1515
  if (inner) {
1550
1516
  const merged = mergeComboClasses(inner, combo, root.className);
@@ -1570,17 +1536,13 @@ async function emitInlineComponentBody(
1570
1536
  if (root && typeof root === 'object') {
1571
1537
  root.attributes = root.attributes || {};
1572
1538
  const existing = root.attributes['data-component'];
1573
- root.attributes['data-component'] = existing
1574
- ? `${existing} ${node.component}`
1575
- : node.component;
1539
+ root.attributes['data-component'] = existing ? `${existing} ${node.component}` : node.component;
1576
1540
 
1577
1541
  // Serialize defineVars-exposed props into data-props, keyed by component
1578
1542
  // name so nested components don't clobber each other on a shared root.
1579
1543
  const defineVars = structured.defineVars;
1580
1544
  if (defineVars) {
1581
- const varsToExpose = defineVars === true
1582
- ? Object.keys(structured.interface || {})
1583
- : defineVars;
1545
+ const varsToExpose = defineVars === true ? Object.keys(structured.interface || {}) : defineVars;
1584
1546
  const propsForJS: Record<string, unknown> = {};
1585
1547
  for (const varName of varsToExpose) {
1586
1548
  if (resolvedProps[varName] !== undefined) {
@@ -1597,7 +1559,9 @@ async function emitInlineComponentBody(
1597
1559
  if (parsed && typeof parsed === 'object') {
1598
1560
  existingPropsMap = parsed as Record<string, unknown>;
1599
1561
  }
1600
- } catch { /* ignore malformed */ }
1562
+ } catch {
1563
+ /* ignore malformed */
1564
+ }
1601
1565
  }
1602
1566
  existingPropsMap[node.component] = propsForJS;
1603
1567
  // URL-encode the serialized JSON. Webflow's `<DOM>`-type element
@@ -1616,7 +1580,7 @@ async function emitInlineComponentBody(
1616
1580
  async function emitSlotMarker(
1617
1581
  node: SlotMarker,
1618
1582
  ctx: WebflowEmitContext,
1619
- instanceProps?: Record<string, unknown>
1583
+ instanceProps?: Record<string, unknown>,
1620
1584
  ): Promise<WebflowElement[]> {
1621
1585
  // Use instance children passed via context to fill the slot
1622
1586
  if (ctx.slotChildren) {
@@ -1655,28 +1619,26 @@ async function emitSlotMarker(
1655
1619
  async function emitEmbedNode(
1656
1620
  node: EmbedNode,
1657
1621
  ctx: WebflowEmitContext,
1658
- instanceProps?: Record<string, unknown>
1622
+ instanceProps?: Record<string, unknown>,
1659
1623
  ): Promise<WebflowElement> {
1660
1624
  const style = substituteVarsInStyle(
1661
- resolveStyleTemplates(
1662
- node.style as StyleObject | ResponsiveStyleObject | undefined,
1663
- instanceProps
1664
- ),
1665
- ctx
1625
+ resolveStyleTemplates(node.style as StyleObject | ResponsiveStyleObject | undefined, instanceProps),
1626
+ ctx,
1666
1627
  );
1667
1628
  const interactiveStyles = substituteVarsInInteractive(
1668
- resolveInteractiveStyleTemplates(
1669
- node.interactiveStyles as InteractiveStyles | undefined,
1670
- instanceProps
1671
- ),
1672
- ctx
1629
+ resolveInteractiveStyleTemplates(node.interactiveStyles as InteractiveStyles | undefined, instanceProps),
1630
+ ctx,
1673
1631
  );
1674
1632
 
1675
1633
  let className: string | undefined;
1676
1634
  if (style || (interactiveStyles && interactiveStyles.length > 0)) {
1677
1635
  const elementClass = withThemeSuffix(buildElementClass(ctx, node.label), ctx);
1678
1636
  const { primaryClass } = mapStylesToWebflow(
1679
- elementClass, style, interactiveStyles, ctx.breakpoints, ctx.responsiveScales
1637
+ elementClass,
1638
+ style,
1639
+ interactiveStyles,
1640
+ ctx.breakpoints,
1641
+ ctx.responsiveScales,
1680
1642
  );
1681
1643
  substituteVarsInStyleClass(primaryClass, ctx);
1682
1644
  className = primaryClass.name;
@@ -1777,7 +1739,7 @@ function resolveLinkHref(rawHref: string, ctx: WebflowEmitContext): string {
1777
1739
  ctx.locale,
1778
1740
  ctx.i18nConfig.defaultLocale,
1779
1741
  ctx.i18nConfig.defaultLocale,
1780
- ctx.slugIndex
1742
+ ctx.slugIndex,
1781
1743
  );
1782
1744
 
1783
1745
  return translated + suffix;
@@ -1786,21 +1748,15 @@ function resolveLinkHref(rawHref: string, ctx: WebflowEmitContext): string {
1786
1748
  async function emitLinkNode(
1787
1749
  node: LinkNode,
1788
1750
  ctx: WebflowEmitContext,
1789
- instanceProps?: Record<string, unknown>
1751
+ instanceProps?: Record<string, unknown>,
1790
1752
  ): Promise<WebflowElement> {
1791
1753
  const style = substituteVarsInStyle(
1792
- resolveStyleTemplates(
1793
- node.style as StyleObject | ResponsiveStyleObject | undefined,
1794
- instanceProps
1795
- ),
1796
- ctx
1754
+ resolveStyleTemplates(node.style as StyleObject | ResponsiveStyleObject | undefined, instanceProps),
1755
+ ctx,
1797
1756
  );
1798
1757
  const interactiveStyles = substituteVarsInInteractive(
1799
- resolveInteractiveStyleTemplates(
1800
- node.interactiveStyles as InteractiveStyles | undefined,
1801
- instanceProps
1802
- ),
1803
- ctx
1758
+ resolveInteractiveStyleTemplates(node.interactiveStyles as InteractiveStyles | undefined, instanceProps),
1759
+ ctx,
1804
1760
  );
1805
1761
 
1806
1762
  // Always assign a class so we can default `text-decoration: none` —
@@ -1811,8 +1767,12 @@ async function emitLinkNode(
1811
1767
  {
1812
1768
  const elementClass = withThemeSuffix(buildElementClass(ctx, node.label), ctx);
1813
1769
  const { primaryClass, comboClasses } = mapStylesToWebflow(
1814
- elementClass, style, interactiveStyles, ctx.breakpoints, ctx.responsiveScales,
1815
- { instanceProps, componentDefaults: ctx.componentDefaults, themeSuffix: themedClassSuffix(ctx) }
1770
+ elementClass,
1771
+ style,
1772
+ interactiveStyles,
1773
+ ctx.breakpoints,
1774
+ ctx.responsiveScales,
1775
+ { instanceProps, componentDefaults: ctx.componentDefaults, themeSuffix: themedClassSuffix(ctx) },
1816
1776
  );
1817
1777
  substituteVarsInStyleClass(primaryClass, ctx);
1818
1778
  applyLinkTextDecorationDefault(primaryClass);
@@ -1829,11 +1789,7 @@ async function emitLinkNode(
1829
1789
  }
1830
1790
  }
1831
1791
 
1832
- if (
1833
- ctx.interactiveStylesMap
1834
- && Array.isArray(interactiveStyles)
1835
- && interactiveStyles.length > 0
1836
- ) {
1792
+ if (ctx.interactiveStylesMap && Array.isArray(interactiveStyles) && interactiveStyles.length > 0) {
1837
1793
  ctx.interactiveStylesMap.set(primaryClass.name, interactiveStyles);
1838
1794
  }
1839
1795
  }
@@ -1851,9 +1807,7 @@ async function emitLinkNode(
1851
1807
  const attributes: Record<string, string | number | boolean> = { href };
1852
1808
  if (node.attributes) {
1853
1809
  for (const [key, value] of Object.entries(node.attributes)) {
1854
- attributes[key] = (typeof value === 'string')
1855
- ? resolveStringTemplate(value, ctx, instanceProps)
1856
- : value;
1810
+ attributes[key] = typeof value === 'string' ? resolveStringTemplate(value, ctx, instanceProps) : value;
1857
1811
  }
1858
1812
  }
1859
1813
 
@@ -1905,7 +1859,7 @@ function resolveItemI18n(item: CMSItem, ctx: WebflowEmitContext): CMSItem {
1905
1859
  async function getCollectionItemsForExport(
1906
1860
  node: ListNode,
1907
1861
  source: string,
1908
- ctx: WebflowEmitContext
1862
+ ctx: WebflowEmitContext,
1909
1863
  ): Promise<CMSItem[]> {
1910
1864
  if (!ctx.cmsService) return [];
1911
1865
 
@@ -1923,16 +1877,16 @@ async function getCollectionItemsForExport(
1923
1877
  for (const part of fieldPath.split('.')) {
1924
1878
  if (value && typeof value === 'object' && part in (value as object)) {
1925
1879
  value = (value as Record<string, unknown>)[part];
1926
- } else { value = undefined; break; }
1880
+ } else {
1881
+ value = undefined;
1882
+ break;
1883
+ }
1927
1884
  }
1928
1885
  if (value !== null && value !== undefined) {
1929
- resolvedIds = Array.isArray(value) ? value.map(v => String(v)) : String(value);
1886
+ resolvedIds = Array.isArray(value) ? value.map((v) => String(v)) : String(value);
1930
1887
  }
1931
1888
  } else {
1932
- resolvedIds = resolveItemsTemplate(
1933
- itemsField,
1934
- (ctx.templateContext || { _type: 'template' }) as any
1935
- );
1889
+ resolvedIds = resolveItemsTemplate(itemsField, (ctx.templateContext || { _type: 'template' }) as any);
1936
1890
  }
1937
1891
  if (!resolvedIds) return [];
1938
1892
  const ids = Array.isArray(resolvedIds) ? resolvedIds : [resolvedIds];
@@ -1942,7 +1896,7 @@ async function getCollectionItemsForExport(
1942
1896
  items = await ctx.cmsService.getItemsByIds(source, ids);
1943
1897
  }
1944
1898
  if (ctx.locale) {
1945
- items = items.filter(it => !isItemDraftForLocale(it, ctx.locale!));
1899
+ items = items.filter((it) => !isItemDraftForLocale(it, ctx.locale!));
1946
1900
  }
1947
1901
  } else {
1948
1902
  items = await ctx.cmsService.queryItems({
@@ -1957,13 +1911,17 @@ async function getCollectionItemsForExport(
1957
1911
 
1958
1912
  if ((node as any).excludeCurrentItem && ctx.cmsContext?.cms?._id) {
1959
1913
  const currentId = ctx.cmsContext.cms._id as string;
1960
- items = items.filter(it => it._id !== currentId);
1914
+ items = items.filter((it) => it._id !== currentId);
1961
1915
  }
1962
1916
 
1963
1917
  return items;
1964
1918
  }
1965
1919
 
1966
- function getPropItemsForExport(source: string, ctx: WebflowEmitContext, instanceProps?: Record<string, unknown>): unknown[] {
1920
+ function getPropItemsForExport(
1921
+ source: string,
1922
+ ctx: WebflowEmitContext,
1923
+ instanceProps?: Record<string, unknown>,
1924
+ ): unknown[] {
1967
1925
  // Template expression like "{{items}}" or "{{category.items}}". SSR pre-
1968
1926
  // substitutes these against the merged prop scope via `processStructure`
1969
1927
  // before the list node is reached, so its `getPropItems` only needs to look
@@ -2086,10 +2044,7 @@ function applyBindingMarkers(el: WebflowElement): void {
2086
2044
 
2087
2045
  // Image inlining produced bytes for a sentinel src — drop them; user will
2088
2046
  // re-bind the image to a real CMS field after insertion.
2089
- if (
2090
- el.menoBind?.attrFields?.src
2091
- && (el.imageDataBase64 || el.imageSrc)
2092
- ) {
2047
+ if (el.menoBind?.attrFields?.src && (el.imageDataBase64 || el.imageSrc)) {
2093
2048
  delete el.imageDataBase64;
2094
2049
  delete el.imageDataMime;
2095
2050
  delete el.imageDataFileName;
@@ -2119,9 +2074,7 @@ function applyBindingMarkers(el: WebflowElement): void {
2119
2074
  * Walks recursively, in-place. Idempotent: existing `<li>` children pass
2120
2075
  * through untouched.
2121
2076
  */
2122
- export function normalizeListChildren(
2123
- elements: Array<WebflowElement | string> | undefined
2124
- ): void {
2077
+ export function normalizeListChildren(elements: Array<WebflowElement | string> | undefined): void {
2125
2078
  if (!Array.isArray(elements)) return;
2126
2079
  for (const el of elements) {
2127
2080
  if (typeof el === 'string') continue;
@@ -2147,11 +2100,11 @@ export function normalizeListChildren(
2147
2100
  async function emitListNode(
2148
2101
  node: ListNode,
2149
2102
  ctx: WebflowEmitContext,
2150
- instanceProps?: Record<string, unknown>
2103
+ instanceProps?: Record<string, unknown>,
2151
2104
  ): Promise<WebflowElement[]> {
2152
2105
  const nodeType = node.type as string;
2153
2106
  const isLegacyCMSList = nodeType === 'cms-list';
2154
- const sourceType = isLegacyCMSList ? 'collection' : (node.sourceType || 'prop');
2107
+ const sourceType = isLegacyCMSList ? 'collection' : node.sourceType || 'prop';
2155
2108
 
2156
2109
  if (sourceType === 'collection' && !ctx.cmsService) return [];
2157
2110
 
@@ -2171,13 +2124,7 @@ async function emitListNode(
2171
2124
  if (sourceType === 'collection' && ctx.bindCollectionLists && ctx.cmsService && source) {
2172
2125
  const schema = ctx.cmsService.getSchema(source) || undefined;
2173
2126
  const placeholder = buildBindingPlaceholderItem(schema);
2174
- const templateContext = buildTemplateContext(
2175
- variableName,
2176
- placeholder,
2177
- 0,
2178
- 1,
2179
- ctx.templateContext as any
2180
- );
2127
+ const templateContext = buildTemplateContext(variableName, placeholder, 0, 1, ctx.templateContext as any);
2181
2128
  const childCtx: WebflowEmitContext = {
2182
2129
  ...ctx,
2183
2130
  templateContext: templateContext as Record<string, unknown>,
@@ -2186,17 +2133,17 @@ async function emitListNode(
2186
2133
  ...(instanceProps || {}),
2187
2134
  ...templateContext,
2188
2135
  };
2189
- const renderedChildren = node.children
2190
- ? await convertChildren(node.children as any, childCtx, mergedProps)
2191
- : [];
2136
+ const renderedChildren = node.children ? await convertChildren(node.children as any, childCtx, mergedProps) : [];
2192
2137
  for (const child of renderedChildren) {
2193
2138
  if (typeof child !== 'string') applyBindingMarkers(child);
2194
2139
  }
2195
- return [{
2196
- tag: COLLECTION_LIST_TAG,
2197
- menoCollectionRef: source,
2198
- children: renderedChildren,
2199
- }];
2140
+ return [
2141
+ {
2142
+ tag: COLLECTION_LIST_TAG,
2143
+ menoCollectionRef: source,
2144
+ children: renderedChildren,
2145
+ },
2146
+ ];
2200
2147
  }
2201
2148
 
2202
2149
  let items: unknown[];
@@ -2221,29 +2168,22 @@ async function expandListItems(
2221
2168
  instanceProps: Record<string, unknown> | undefined,
2222
2169
  items: unknown[],
2223
2170
  variableName: string,
2224
- source: string
2171
+ source: string,
2225
2172
  ): Promise<WebflowElement[]> {
2226
2173
  if (items.length === 0) return [];
2227
2174
 
2228
- const schema: CMSSchema | undefined = ctx.cmsService
2229
- ? (ctx.cmsService.getSchema(source) || undefined)
2230
- : undefined;
2175
+ const schema: CMSSchema | undefined = ctx.cmsService ? ctx.cmsService.getSchema(source) || undefined : undefined;
2231
2176
 
2232
2177
  const out: WebflowElement[] = [];
2233
2178
  for (let i = 0; i < items.length; i++) {
2234
2179
  const rawItem = items[i] as Record<string, unknown>;
2235
- const enriched = schema && ctx.locale && ctx.i18nConfig
2236
- ? addItemUrl(rawItem as CMSItem, schema, ctx.locale, ctx.i18nConfig)
2237
- : (rawItem as CMSItem);
2180
+ const enriched =
2181
+ schema && ctx.locale && ctx.i18nConfig
2182
+ ? addItemUrl(rawItem as CMSItem, schema, ctx.locale, ctx.i18nConfig)
2183
+ : (rawItem as CMSItem);
2238
2184
  const item = resolveItemI18n(enriched, ctx);
2239
2185
 
2240
- const templateContext = buildTemplateContext(
2241
- variableName,
2242
- item,
2243
- i,
2244
- items.length,
2245
- (ctx.templateContext as any)
2246
- );
2186
+ const templateContext = buildTemplateContext(variableName, item, i, items.length, ctx.templateContext as any);
2247
2187
 
2248
2188
  const childCtx: WebflowEmitContext = {
2249
2189
  ...ctx,
@@ -2275,7 +2215,7 @@ async function expandListItems(
2275
2215
  async function emitLocaleListNode(
2276
2216
  node: LocaleListNode,
2277
2217
  ctx: WebflowEmitContext,
2278
- instanceProps?: Record<string, unknown>
2218
+ instanceProps?: Record<string, unknown>,
2279
2219
  ): Promise<WebflowElement[]> {
2280
2220
  if (!ctx.slugMappings || !ctx.pagePath || !ctx.i18nConfig || !ctx.locale) {
2281
2221
  return [{ tag: 'div', attributes: { 'data-locale-list': 'true' } }];
@@ -2298,49 +2238,40 @@ async function emitLocaleListNode(
2298
2238
 
2299
2239
  // Build container style class
2300
2240
  const containerStyle = substituteVarsInStyle(
2301
- resolveStyleTemplates(
2302
- node.style as StyleObject | ResponsiveStyleObject | undefined,
2303
- instanceProps
2304
- ),
2305
- ctx
2241
+ resolveStyleTemplates(node.style as StyleObject | ResponsiveStyleObject | undefined, instanceProps),
2242
+ ctx,
2306
2243
  );
2307
2244
  const containerInteractive = substituteVarsInInteractive(
2308
- resolveInteractiveStyleTemplates(
2309
- node.interactiveStyles as InteractiveStyles | undefined,
2310
- instanceProps
2311
- ),
2312
- ctx
2245
+ resolveInteractiveStyleTemplates(node.interactiveStyles as InteractiveStyles | undefined, instanceProps),
2246
+ ctx,
2313
2247
  );
2314
2248
 
2315
2249
  let containerClass: string | undefined;
2316
2250
  if (containerStyle || (containerInteractive && containerInteractive.length > 0)) {
2317
2251
  const elementClass = withThemeSuffix(buildElementClass(ctx, node.label), ctx);
2318
2252
  const { primaryClass } = mapStylesToWebflow(
2319
- elementClass, containerStyle, containerInteractive, ctx.breakpoints, ctx.responsiveScales
2253
+ elementClass,
2254
+ containerStyle,
2255
+ containerInteractive,
2256
+ ctx.breakpoints,
2257
+ ctx.responsiveScales,
2320
2258
  );
2321
2259
  substituteVarsInStyleClass(primaryClass, ctx);
2322
2260
  containerClass = primaryClass.name;
2323
2261
  ctx.styleClasses.set(primaryClass.name, primaryClass);
2324
2262
  }
2325
2263
 
2326
- const buildSubClass = (
2327
- style: unknown,
2328
- suffix: string
2329
- ): string | undefined => {
2264
+ const buildSubClass = (style: unknown, suffix: string): string | undefined => {
2330
2265
  const resolved = substituteVarsInStyle(
2331
- resolveStyleTemplates(
2332
- style as StyleObject | ResponsiveStyleObject | undefined,
2333
- instanceProps
2334
- ),
2335
- ctx
2266
+ resolveStyleTemplates(style as StyleObject | ResponsiveStyleObject | undefined, instanceProps),
2267
+ ctx,
2336
2268
  );
2337
2269
  if (!resolved) return undefined;
2338
2270
  const className = withThemeSuffix(`${buildElementClass(ctx, node.label)}-${suffix}`, ctx);
2339
2271
  const { primaryClass } = mapStylesToWebflow(className, resolved, undefined, ctx.breakpoints, ctx.responsiveScales);
2340
2272
  substituteVarsInStyleClass(primaryClass, ctx);
2341
- if (Object.keys(primaryClass.base).length === 0
2342
- && !primaryClass.breakpoints
2343
- && !primaryClass.pseudoStates) return undefined;
2273
+ if (Object.keys(primaryClass.base).length === 0 && !primaryClass.breakpoints && !primaryClass.pseudoStates)
2274
+ return undefined;
2344
2275
  ctx.styleClasses.set(primaryClass.name, primaryClass);
2345
2276
  return primaryClass.name;
2346
2277
  };
@@ -2390,10 +2321,16 @@ async function emitLocaleListNode(
2390
2321
 
2391
2322
  let displayText: string;
2392
2323
  switch (displayType) {
2393
- case 'code': displayText = link.locale.toUpperCase(); break;
2394
- case 'name': displayText = link.name; break;
2324
+ case 'code':
2325
+ displayText = link.locale.toUpperCase();
2326
+ break;
2327
+ case 'name':
2328
+ displayText = link.name;
2329
+ break;
2395
2330
  case 'nativeName':
2396
- default: displayText = link.nativeName; break;
2331
+ default:
2332
+ displayText = link.nativeName;
2333
+ break;
2397
2334
  }
2398
2335
  innerChildren.push({ tag: 'div', textContent: displayText });
2399
2336
  anchor.children = innerChildren;
@@ -2418,7 +2355,7 @@ async function emitLocaleListNode(
2418
2355
  async function convertChildren(
2419
2356
  children: (ComponentNode | string)[] | string | ComponentNode | null | undefined,
2420
2357
  ctx: WebflowEmitContext,
2421
- instanceProps?: Record<string, unknown>
2358
+ instanceProps?: Record<string, unknown>,
2422
2359
  ): Promise<WebflowElement[]> {
2423
2360
  if (!children) return [];
2424
2361