meno-core 1.0.53 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +1 -3
- package/bin/cli.ts +66 -261
- package/build-astro.ts +150 -128
- package/dist/bin/cli.js +42 -185
- package/dist/bin/cli.js.map +2 -2
- package/dist/chunks/chunk-2AR55GYH.js +42 -0
- package/dist/chunks/chunk-2AR55GYH.js.map +7 -0
- package/dist/chunks/{chunk-JGWFTO6P.js → chunk-2IIQK7T3.js} +2624 -1389
- package/dist/chunks/chunk-2IIQK7T3.js.map +7 -0
- package/dist/chunks/chunk-4ZRU52J2.js +169 -0
- package/dist/chunks/chunk-4ZRU52J2.js.map +7 -0
- package/dist/chunks/{chunk-UB44F4Z2.js → chunk-5X4HCN7J.js} +5 -7
- package/dist/chunks/chunk-5X4HCN7J.js.map +7 -0
- package/dist/chunks/{chunk-WQFG7PAH.js → chunk-7CCVOL5M.js} +15 -19
- package/dist/chunks/chunk-7CCVOL5M.js.map +7 -0
- package/dist/chunks/{chunk-YBLHKYFF.js → chunk-AR7LHIFY.js} +8 -2
- package/dist/chunks/chunk-AR7LHIFY.js.map +7 -0
- package/dist/chunks/{chunk-O3NAGJP4.js → chunk-NUP7H7D3.js} +135 -41
- package/dist/chunks/chunk-NUP7H7D3.js.map +7 -0
- package/dist/chunks/{chunk-X754AHS5.js → chunk-QWTQZHG3.js} +194 -90
- package/dist/chunks/chunk-QWTQZHG3.js.map +7 -0
- package/dist/chunks/{chunk-H3GJ4H2U.js → chunk-XTKNX4FW.js} +216 -87
- package/dist/chunks/chunk-XTKNX4FW.js.map +7 -0
- package/dist/chunks/{fs-JGINUXGL.js → fs-G3ANWEFP.js} +2 -2
- package/dist/lib/client/index.js +1003 -475
- package/dist/lib/client/index.js.map +3 -3
- package/dist/lib/server/index.js +14393 -6371
- package/dist/lib/server/index.js.map +4 -4
- package/dist/lib/shared/index.js +342 -101
- package/dist/lib/shared/index.js.map +4 -4
- package/dist/lib/shared/richtext/index.js +1 -1
- package/dist/lib/test-utils/index.js +64 -80
- package/dist/lib/test-utils/index.js.map +2 -2
- package/entries/client-router.tsx +10 -8
- package/lib/client/ClientInitializer.ts +8 -8
- package/lib/client/ErrorBoundary.test.tsx +246 -186
- package/lib/client/ErrorBoundary.tsx +183 -132
- package/lib/client/componentRegistry.test.ts +96 -108
- package/lib/client/componentRegistry.ts +1 -3
- package/lib/client/contexts/ThemeContext.tsx +3 -2
- package/lib/client/core/ComponentBuilder.test.ts +663 -560
- package/lib/client/core/ComponentBuilder.ts +427 -155
- package/lib/client/core/ComponentRenderer.test.tsx +2 -4
- package/lib/client/core/ComponentRenderer.tsx +46 -33
- package/lib/client/core/builders/embedBuilder.ts +242 -54
- package/lib/client/core/builders/linkBuilder.ts +72 -45
- package/lib/client/core/builders/linkNodeBuilder.ts +79 -54
- package/lib/client/core/builders/listBuilder.ts +155 -89
- package/lib/client/core/builders/localeListBuilder.ts +97 -62
- package/lib/client/core/builders/types.ts +5 -5
- package/lib/client/core/cmsTemplateProcessor.ts +8 -9
- package/lib/client/elementRegistry.ts +3 -3
- package/lib/client/fontFamiliesService.test.ts +2 -10
- package/lib/client/fontFamiliesService.ts +3 -3
- package/lib/client/hmr/HMRManager.tsx +47 -30
- package/lib/client/hmrCssReload.ts +49 -14
- package/lib/client/hmrWebSocket.ts +14 -19
- package/lib/client/hooks/useColorVariables.test.ts +21 -21
- package/lib/client/hooks/useColorVariables.ts +23 -18
- package/lib/client/hooks/usePropertyAutocomplete.ts +4 -6
- package/lib/client/hooks/useVariables.ts +6 -4
- package/lib/client/hydration/HydrationUtils.test.ts +24 -25
- package/lib/client/hydration/HydrationUtils.ts +3 -4
- package/lib/client/i18nConfigService.test.ts +2 -7
- package/lib/client/i18nConfigService.ts +2 -2
- package/lib/client/meno-filter/MenoFilter.test.ts +47 -49
- package/lib/client/meno-filter/MenoFilter.ts +14 -15
- package/lib/client/meno-filter/bindings.ts +18 -43
- package/lib/client/meno-filter/init.ts +4 -4
- package/lib/client/meno-filter/renderer.ts +30 -32
- package/lib/client/meno-filter/script.generated.ts +1 -3
- package/lib/client/meno-filter/ui.ts +4 -6
- package/lib/client/meno-filter/updates.ts +18 -23
- package/lib/client/meno-filter/utils.ts +1 -1
- package/lib/client/navigation.test.ts +174 -178
- package/lib/client/navigation.ts +0 -1
- package/lib/client/responsiveStyleResolver.knownTokens.test.ts +71 -0
- package/lib/client/responsiveStyleResolver.test.ts +234 -232
- package/lib/client/responsiveStyleResolver.ts +74 -20
- package/lib/client/routing/RouteLoader.test.ts +24 -25
- package/lib/client/routing/RouteLoader.ts +27 -35
- package/lib/client/routing/Router.tsx +210 -153
- package/lib/client/scripts/ScriptExecutor.test.ts +157 -158
- package/lib/client/scripts/ScriptExecutor.ts +18 -36
- package/lib/client/services/PrefetchService.test.ts +3 -3
- package/lib/client/services/PrefetchService.ts +23 -29
- package/lib/client/styleProcessor.test.ts +9 -9
- package/lib/client/styleProcessor.ts +24 -15
- package/lib/client/styles/StyleInjector.test.ts +122 -115
- package/lib/client/styles/StyleInjector.ts +10 -7
- package/lib/client/styles/UtilityClassCollector.ts +62 -28
- package/lib/client/styles/cspNonce.test.ts +2 -5
- package/lib/client/templateEngine.test.ts +554 -488
- package/lib/client/templateEngine.ts +203 -73
- package/lib/client/theme.test.ts +1 -1
- package/lib/client/theme.ts +0 -1
- package/lib/client/utils/toast.ts +0 -1
- package/lib/server/__integration__/api-routes.test.ts +8 -4
- package/lib/server/__integration__/cms-integration.test.ts +1 -4
- package/lib/server/__integration__/server-lifecycle.test.ts +4 -5
- package/lib/server/__integration__/ssr-rendering.test.ts +47 -37
- package/lib/server/__integration__/static-assets.test.ts +3 -3
- package/lib/server/__integration__/test-helpers.ts +87 -74
- package/lib/server/ab/generateFunctions.ts +12 -10
- package/lib/server/astro/cmsPageEmitter.ts +26 -42
- package/lib/server/astro/componentEmitter.ts +35 -43
- package/lib/server/astro/cssCollector.ts +10 -26
- package/lib/server/astro/nodeToAstro.test.ts +1754 -34
- package/lib/server/astro/nodeToAstro.ts +232 -216
- package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +115 -119
- package/lib/server/astro/normalizeOrphanTemplateProps.ts +11 -18
- package/lib/server/astro/pageEmitter.ts +9 -13
- package/lib/server/astro/tailwindMapper.test.ts +10 -37
- package/lib/server/astro/tailwindMapper.ts +33 -40
- package/lib/server/astro/templateTransformer.ts +17 -20
- package/lib/server/createServer.ts +7 -19
- package/lib/server/cssGenerator.test.ts +35 -44
- package/lib/server/cssGenerator.ts +8 -19
- package/lib/server/fileWatcher.test.ts +164 -13
- package/lib/server/fileWatcher.ts +209 -124
- package/lib/server/index.ts +14 -17
- package/lib/server/jsonLoader.test.ts +39 -2
- package/lib/server/jsonLoader.ts +39 -34
- package/lib/server/middleware/cors.test.ts +21 -21
- package/lib/server/middleware/cors.ts +28 -4
- package/lib/server/middleware/errorHandler.test.ts +7 -5
- package/lib/server/middleware/errorHandler.ts +3 -8
- package/lib/server/middleware/index.ts +0 -1
- package/lib/server/middleware/logger.test.ts +10 -8
- package/lib/server/middleware/logger.ts +17 -29
- package/lib/server/migrateTemplates.ts +3 -3
- package/lib/server/pageCache.test.ts +76 -77
- package/lib/server/pageCache.ts +0 -1
- package/lib/server/projectContext.ts +5 -4
- package/lib/server/providers/fileSystemCMSProvider.test.ts +142 -99
- package/lib/server/providers/fileSystemCMSProvider.ts +62 -38
- package/lib/server/routes/api/cms.test.ts +26 -14
- package/lib/server/routes/api/cms.ts +9 -14
- package/lib/server/routes/api/colors.test.ts +2 -2
- package/lib/server/routes/api/components.ts +31 -35
- package/lib/server/routes/api/config.ts +3 -4
- package/lib/server/routes/api/core-routes.ts +49 -76
- package/lib/server/routes/api/enums.test.ts +2 -2
- package/lib/server/routes/api/functions.ts +9 -17
- package/lib/server/routes/api/index.ts +3 -6
- package/lib/server/routes/api/pages.ts +8 -11
- package/lib/server/routes/api/shared.test.ts +1 -1
- package/lib/server/routes/api/shared.ts +12 -9
- package/lib/server/routes/api/variables.test.ts +3 -5
- package/lib/server/routes/api/variables.ts +1 -1
- package/lib/server/routes/index.ts +25 -28
- package/lib/server/routes/pages.ts +35 -31
- package/lib/server/routes/static.ts +17 -6
- package/lib/server/runtime/bundler.ts +98 -61
- package/lib/server/runtime/fs.ts +16 -26
- package/lib/server/runtime/httpServer.ts +8 -12
- package/lib/server/services/ColorService.test.ts +3 -3
- package/lib/server/services/ColorService.ts +37 -29
- package/lib/server/services/EnumService.test.ts +4 -8
- package/lib/server/services/EnumService.ts +11 -3
- package/lib/server/services/VariableService.test.ts +8 -12
- package/lib/server/services/VariableService.ts +11 -3
- package/lib/server/services/cmsService.test.ts +158 -120
- package/lib/server/services/cmsService.ts +36 -146
- package/lib/server/services/componentService.test.ts +125 -45
- package/lib/server/services/componentService.ts +70 -46
- package/lib/server/services/configService.test.ts +22 -45
- package/lib/server/services/configService.ts +50 -27
- package/lib/server/services/fileWatcherService.ts +42 -8
- package/lib/server/services/index.ts +0 -1
- package/lib/server/services/pageService.test.ts +8 -10
- package/lib/server/services/pageService.ts +32 -18
- package/lib/server/ssr/attributeBuilder.ts +18 -8
- package/lib/server/ssr/buildErrorOverlay.ts +11 -12
- package/lib/server/ssr/clientDataInjector.ts +7 -21
- package/lib/server/ssr/cmsSSRProcessor.ts +4 -8
- package/lib/server/ssr/cssCollector.ts +1 -1
- package/lib/server/ssr/errorOverlay.test.ts +1 -1
- package/lib/server/ssr/errorOverlay.ts +3 -9
- package/lib/server/ssr/htmlGenerator.nonce.test.ts +9 -14
- package/lib/server/ssr/htmlGenerator.test.ts +120 -44
- package/lib/server/ssr/htmlGenerator.ts +126 -91
- package/lib/server/ssr/imageMetadata.test.ts +3 -1
- package/lib/server/ssr/imageMetadata.ts +27 -21
- package/lib/server/ssr/jsCollector.test.ts +8 -18
- package/lib/server/ssr/jsCollector.ts +3 -8
- package/lib/server/ssr/liveReloadIntegration.test.ts +76 -36
- package/lib/server/ssr/metaTagGenerator.ts +2 -2
- package/lib/server/ssr/ssrRenderer.branches.test.ts +1103 -0
- package/lib/server/ssr/ssrRenderer.test.ts +316 -256
- package/lib/server/ssr/ssrRenderer.ts +795 -243
- package/lib/server/ssrRenderer.test.ts +1048 -954
- package/lib/server/utils/jsonLineMapper.test.ts +28 -28
- package/lib/server/utils/jsonLineMapper.ts +7 -7
- package/lib/server/validateStyleCoverage.ts +18 -21
- package/lib/server/websocketManager.ts +28 -19
- package/lib/shared/attributeNodeUtils.test.ts +15 -15
- package/lib/shared/attributeNodeUtils.ts +5 -12
- package/lib/shared/breakpoints.test.ts +5 -5
- package/lib/shared/breakpoints.ts +4 -11
- package/lib/shared/cmsQuery.test.ts +81 -0
- package/lib/shared/cmsQuery.ts +92 -0
- package/lib/shared/cmsQueryParser.test.ts +50 -42
- package/lib/shared/cmsQueryParser.ts +60 -38
- package/lib/shared/colorConversions.ts +9 -9
- package/lib/shared/colorVariableUtils.test.ts +27 -5
- package/lib/shared/colorVariableUtils.ts +21 -12
- package/lib/shared/componentRefs.ts +1 -5
- package/lib/shared/constants.test.ts +3 -3
- package/lib/shared/constants.ts +8 -8
- package/lib/shared/cssGeneration.test.ts +285 -144
- package/lib/shared/cssGeneration.ts +217 -531
- package/lib/shared/cssNamedColors.ts +152 -30
- package/lib/shared/cssProperties.test.ts +69 -70
- package/lib/shared/cssProperties.ts +298 -114
- package/lib/shared/elementClassName.test.ts +109 -109
- package/lib/shared/elementClassName.ts +3 -3
- package/lib/shared/elementUtils.ts +12 -16
- package/lib/shared/errorLogger.test.ts +12 -12
- package/lib/shared/errorLogger.ts +2 -10
- package/lib/shared/errors.test.ts +2 -13
- package/lib/shared/errors.ts +2 -8
- package/lib/shared/expressionEvaluator.test.ts +145 -0
- package/lib/shared/expressionEvaluator.ts +52 -24
- package/lib/shared/fontLoader.test.ts +32 -18
- package/lib/shared/fontLoader.ts +2 -2
- package/lib/shared/friendlyError.ts +2 -3
- package/lib/shared/gradientUtils.test.ts +3 -7
- package/lib/shared/gradientUtils.ts +17 -14
- package/lib/shared/hrefRefs.test.ts +2 -2
- package/lib/shared/hrefRefs.ts +2 -10
- package/lib/shared/i18n.test.ts +4 -4
- package/lib/shared/i18n.ts +18 -38
- package/lib/shared/index.ts +27 -0
- package/lib/shared/inlineSvgStyleRules.ts +14 -13
- package/lib/shared/interactiveStyleMappings.test.ts +32 -54
- package/lib/shared/interactiveStyleMappings.ts +11 -24
- package/lib/shared/interactiveStyles.test.ts +165 -188
- package/lib/shared/interfaces/contentProvider.ts +1 -1
- package/lib/shared/itemTemplateUtils.test.ts +11 -17
- package/lib/shared/itemTemplateUtils.ts +27 -39
- package/lib/shared/jsonRepair.ts +16 -10
- package/lib/shared/libraryLoader.test.ts +21 -55
- package/lib/shared/libraryLoader.ts +7 -22
- package/lib/shared/linkUtils.ts +1 -1
- package/lib/shared/logger.test.ts +66 -0
- package/lib/shared/logger.ts +94 -0
- package/lib/shared/markdown.ts +25 -0
- package/lib/shared/netlifyLocale404.test.ts +179 -0
- package/lib/shared/netlifyLocale404.ts +110 -0
- package/lib/shared/nodeUtils.test.ts +28 -16
- package/lib/shared/nodeUtils.ts +76 -23
- package/lib/shared/pathArrayUtils.test.ts +1 -2
- package/lib/shared/pathArrayUtils.ts +1 -1
- package/lib/shared/pathSecurity.ts +2 -2
- package/lib/shared/pathUtils.test.ts +4 -6
- package/lib/shared/pathUtils.ts +42 -49
- package/lib/shared/paths/Path.test.ts +2 -2
- package/lib/shared/paths/Path.ts +0 -1
- package/lib/shared/paths/PathConverter.test.ts +1 -1
- package/lib/shared/paths/PathConverter.ts +17 -20
- package/lib/shared/paths/PathUtils.ts +13 -13
- package/lib/shared/paths/PathValidator.test.ts +2 -15
- package/lib/shared/paths/PathValidator.ts +12 -10
- package/lib/shared/paths/index.ts +1 -2
- package/lib/shared/permissions.test.ts +168 -0
- package/lib/shared/permissions.ts +162 -0
- package/lib/shared/propResolver.test.ts +240 -244
- package/lib/shared/propResolver.ts +15 -26
- package/lib/shared/pxToRem.test.ts +7 -6
- package/lib/shared/pxToRem.ts +2 -5
- package/lib/shared/registry/BaseNodeTypeRegistry.test.ts +12 -6
- package/lib/shared/registry/ClientRegistry.ts +0 -2
- package/lib/shared/registry/ComponentRegistry.test.ts +46 -32
- package/lib/shared/registry/ComponentRegistry.ts +12 -9
- package/lib/shared/registry/NodeTypeDefinition.ts +16 -9
- package/lib/shared/registry/RegistryManager.ts +1 -2
- package/lib/shared/registry/SSRRegistry.ts +0 -2
- package/lib/shared/registry/createNodeType.ts +7 -9
- package/lib/shared/registry/defineNodeType.ts +2 -6
- package/lib/shared/registry/fieldPresets.ts +3 -1
- package/lib/shared/registry/index.ts +0 -1
- package/lib/shared/registry/nodeTypes/ComponentInstanceNodeType.ts +14 -15
- package/lib/shared/registry/nodeTypes/CustomNodeType.ts +103 -0
- package/lib/shared/registry/nodeTypes/EmbedNodeType.ts +18 -11
- package/lib/shared/registry/nodeTypes/HtmlNodeType.ts +48 -19
- package/lib/shared/registry/nodeTypes/IslandNodeType.ts +129 -0
- package/lib/shared/registry/nodeTypes/LinkNodeType.ts +21 -19
- package/lib/shared/registry/nodeTypes/ListNodeType.ts +117 -77
- package/lib/shared/registry/nodeTypes/LocaleListNodeType.ts +27 -21
- package/lib/shared/registry/nodeTypes/MarkdownNodeType.ts +78 -0
- package/lib/shared/registry/nodeTypes/SlotMarkerType.ts +12 -8
- package/lib/shared/registry/nodeTypes/index.ts +26 -3
- package/lib/shared/responsiveScaling.test.ts +16 -34
- package/lib/shared/responsiveScaling.ts +61 -42
- package/lib/shared/responsiveStyleUtils.test.ts +0 -1
- package/lib/shared/responsiveStyleUtils.ts +11 -13
- package/lib/shared/richtext/htmlToTiptap.test.ts +139 -130
- package/lib/shared/richtext/htmlToTiptap.ts +2 -4
- package/lib/shared/richtext/tiptapToHtml.test.ts +5 -6
- package/lib/shared/richtext/types.ts +1 -8
- package/lib/shared/slugTranslator.test.ts +13 -13
- package/lib/shared/slugTranslator.ts +12 -16
- package/lib/shared/slugify.ts +9 -15
- package/lib/shared/styleNodeUtils.test.ts +8 -8
- package/lib/shared/styleNodeUtils.ts +18 -20
- package/lib/shared/styleUtils.test.ts +87 -61
- package/lib/shared/styleUtils.ts +5 -6
- package/lib/shared/themeDefaults.test.ts +11 -14
- package/lib/shared/themeDefaults.ts +3 -4
- package/lib/shared/tree/PathBuilder.test.ts +63 -145
- package/lib/shared/tree/PathBuilder.ts +59 -47
- package/lib/shared/treePathUtils.test.ts +51 -12
- package/lib/shared/treePathUtils.ts +91 -60
- package/lib/shared/types/api.ts +105 -8
- package/lib/shared/types/cms.test.ts +34 -0
- package/lib/shared/types/cms.ts +90 -34
- package/lib/shared/types/comment.ts +49 -16
- package/lib/shared/types/components.ts +51 -25
- package/lib/shared/types/errors.test.ts +1 -6
- package/lib/shared/types/errors.ts +3 -7
- package/lib/shared/types/experiments.ts +28 -28
- package/lib/shared/types/index.ts +25 -2
- package/lib/shared/types/permissions.ts +139 -0
- package/lib/shared/types/styles.ts +0 -1
- package/lib/shared/types/variables.test.ts +4 -13
- package/lib/shared/types/variables.ts +51 -30
- package/lib/shared/types.ts +1 -2
- package/lib/shared/utilityClassConfig.ts +751 -321
- package/lib/shared/utilityClassMapper.durability.test.ts +117 -0
- package/lib/shared/utilityClassMapper.test.ts +433 -95
- package/lib/shared/utilityClassMapper.ts +322 -249
- package/lib/shared/utilityClassNames.test.ts +38 -0
- package/lib/shared/utilityClassNames.ts +458 -0
- package/lib/shared/utils.test.ts +2 -10
- package/lib/shared/utils.ts +19 -10
- package/lib/shared/validation/cmsValidators.ts +2 -1
- package/lib/shared/validation/commentValidators.test.ts +53 -0
- package/lib/shared/validation/commentValidators.ts +12 -1
- package/lib/shared/validation/index.ts +1 -0
- package/lib/shared/validation/permissionsValidators.test.ts +49 -0
- package/lib/shared/validation/permissionsValidators.ts +49 -0
- package/lib/shared/validation/propValidator.test.ts +19 -21
- package/lib/shared/validation/propValidator.ts +13 -18
- package/lib/shared/validation/schemas.test.ts +64 -32
- package/lib/shared/validation/schemas.ts +616 -345
- package/lib/shared/validation/validators.test.ts +3 -8
- package/lib/shared/validation/validators.ts +89 -68
- package/lib/shared/viewportUnits.integration.test.ts +14 -10
- package/lib/shared/viewportUnits.test.ts +24 -23
- package/lib/shared/viewportUnits.ts +12 -5
- package/lib/test-utils/dom-setup.ts +1 -1
- package/lib/test-utils/factories/ConsoleMockFactory.ts +10 -14
- package/lib/test-utils/factories/DomMockFactory.ts +17 -23
- package/lib/test-utils/factories/EventMockFactory.ts +7 -13
- package/lib/test-utils/factories/FetchMockFactory.ts +39 -57
- package/lib/test-utils/factories/ServerMockFactory.ts +6 -10
- package/lib/test-utils/factories/StoreMockFactory.ts +18 -29
- package/lib/test-utils/fixtures.ts +45 -45
- package/lib/test-utils/helpers/asyncHelpers.test.ts +15 -18
- package/lib/test-utils/helpers/asyncHelpers.ts +11 -20
- package/lib/test-utils/helpers.ts +1 -5
- package/lib/test-utils/index.ts +0 -4
- package/lib/test-utils/mockFactories.ts +13 -19
- package/lib/test-utils/mocks.ts +6 -4
- package/package.json +3 -5
- package/scripts/build-for-publish.mjs +2 -4
- package/scripts/build-meno-filter.ts +4 -7
- package/tsconfig.json +1 -0
- package/vite.config.ts +4 -4
- package/build-next.ts +0 -1361
- package/build-static.test.ts +0 -424
- package/build-static.ts +0 -1074
- package/dist/build-static.js +0 -36
- package/dist/chunks/chunk-2MHDV5BF.js +0 -251
- package/dist/chunks/chunk-2MHDV5BF.js.map +0 -7
- package/dist/chunks/chunk-AZQYF6KE.js +0 -559
- package/dist/chunks/chunk-AZQYF6KE.js.map +0 -7
- package/dist/chunks/chunk-GZHGVVW3.js +0 -322
- package/dist/chunks/chunk-GZHGVVW3.js.map +0 -7
- package/dist/chunks/chunk-H3GJ4H2U.js.map +0 -7
- package/dist/chunks/chunk-I7YIGZXT.js +0 -467
- package/dist/chunks/chunk-I7YIGZXT.js.map +0 -7
- package/dist/chunks/chunk-IGYR22T6.js +0 -6192
- package/dist/chunks/chunk-IGYR22T6.js.map +0 -7
- package/dist/chunks/chunk-JGP5A3Y5.js +0 -1136
- package/dist/chunks/chunk-JGP5A3Y5.js.map +0 -7
- package/dist/chunks/chunk-JGWFTO6P.js.map +0 -7
- package/dist/chunks/chunk-O3NAGJP4.js.map +0 -7
- package/dist/chunks/chunk-QB2LNO4W.js +0 -77
- package/dist/chunks/chunk-QB2LNO4W.js.map +0 -7
- package/dist/chunks/chunk-R6XHAFBF.js +0 -3821
- package/dist/chunks/chunk-R6XHAFBF.js.map +0 -7
- package/dist/chunks/chunk-UB44F4Z2.js.map +0 -7
- package/dist/chunks/chunk-WQFG7PAH.js.map +0 -7
- package/dist/chunks/chunk-X754AHS5.js.map +0 -7
- package/dist/chunks/chunk-YBLHKYFF.js.map +0 -7
- package/dist/chunks/configService-R3OGU2UD.js +0 -13
- package/dist/chunks/configService-R3OGU2UD.js.map +0 -7
- package/dist/chunks/constants-STK2YBIW.js +0 -46
- package/dist/chunks/constants-STK2YBIW.js.map +0 -7
- package/dist/chunks/fs-JGINUXGL.js.map +0 -7
- package/dist/entries/server-router.js +0 -67
- package/dist/entries/server-router.js.map +0 -7
- package/entries/server-router.tsx +0 -81
- package/lib/server/providers/fileSystemPageProvider.ts +0 -160
- package/lib/server/webflow/buildWebflow.ts +0 -635
- package/lib/server/webflow/index.ts +0 -23
- package/lib/server/webflow/nodeToWebflow.test.ts +0 -3170
- package/lib/server/webflow/nodeToWebflow.ts +0 -2435
- package/lib/server/webflow/styleMapper.test.ts +0 -389
- package/lib/server/webflow/styleMapper.ts +0 -695
- package/lib/server/webflow/templateWrapper.ts +0 -49
- package/lib/server/webflow/types.ts +0 -396
- /package/dist/{build-static.js.map → chunks/fs-G3ANWEFP.js.map} +0 -0
|
@@ -1,635 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Webflow Export Build Orchestrator
|
|
3
|
-
* Loads the project, renders all pages, and converts to Webflow payload.
|
|
4
|
-
* Mirrors the pattern of build-astro.ts.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { existsSync, readdirSync } from 'fs';
|
|
8
|
-
import { readFile } from 'fs/promises';
|
|
9
|
-
import { join } from 'path';
|
|
10
|
-
import {
|
|
11
|
-
loadJSONFile,
|
|
12
|
-
loadComponentDirectory,
|
|
13
|
-
mapPageNameToPath,
|
|
14
|
-
parseJSON,
|
|
15
|
-
loadI18nConfig,
|
|
16
|
-
loadBreakpointConfig,
|
|
17
|
-
} from '../jsonLoader';
|
|
18
|
-
import { renderPageSSR } from '../ssr/ssrRenderer';
|
|
19
|
-
import { projectPaths } from '../projectContext';
|
|
20
|
-
import { loadProjectConfig } from '../../shared/fontLoader';
|
|
21
|
-
import { FileSystemCMSProvider } from '../providers/fileSystemCMSProvider';
|
|
22
|
-
import { CMSService } from '../services/cmsService';
|
|
23
|
-
import { isI18nValue, resolveI18nValue } from '../../shared/i18n';
|
|
24
|
-
import { RAW_HTML_PREFIX } from '../../shared/constants';
|
|
25
|
-
import { extractPageMeta, type PageMeta } from '../ssr/metaTagGenerator';
|
|
26
|
-
import { configService } from '../services/configService';
|
|
27
|
-
import { colorService } from '../services/ColorService';
|
|
28
|
-
import { variableService } from '../services/VariableService';
|
|
29
|
-
import { migrateTemplatesDirectory } from '../migrateTemplates';
|
|
30
|
-
import type {
|
|
31
|
-
ComponentDefinition,
|
|
32
|
-
JSONPage,
|
|
33
|
-
CMSSchema,
|
|
34
|
-
CMSItem,
|
|
35
|
-
I18nConfig,
|
|
36
|
-
ThemeConfig,
|
|
37
|
-
} from '../../shared/types';
|
|
38
|
-
import { resolvePaletteColor } from '../../shared/types/colors';
|
|
39
|
-
import type { SlugMap } from '../../shared/slugTranslator';
|
|
40
|
-
import type {
|
|
41
|
-
WebflowExportPayload,
|
|
42
|
-
WebflowPage,
|
|
43
|
-
WebflowStyleClass,
|
|
44
|
-
WebflowAssetRef,
|
|
45
|
-
WebflowScript,
|
|
46
|
-
WebflowComponentDef,
|
|
47
|
-
} from './types';
|
|
48
|
-
import { nodeToWebflow, normalizeListChildren, type WebflowEmitContext } from './nodeToWebflow';
|
|
49
|
-
import { isWebflowHandledRule } from './styleMapper';
|
|
50
|
-
import { generateInteractiveCSS } from '../../shared/cssGeneration';
|
|
51
|
-
import { generateVariablesCSS } from '../cssGenerator';
|
|
52
|
-
import type { InteractiveStyles } from '../../shared/types/styles';
|
|
53
|
-
import { resolveVariableValueAtBreakpoint } from '../../shared/responsiveScaling';
|
|
54
|
-
import type { ResponsiveScales } from '../../shared/responsiveScaling';
|
|
55
|
-
import type { VariablesConfig } from '../../shared/types';
|
|
56
|
-
import type { BreakpointConfig } from '../../shared/breakpoints';
|
|
57
|
-
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
// Helpers
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
|
|
62
|
-
function scanJSONFiles(dir: string, prefix: string = ''): string[] {
|
|
63
|
-
const results: string[] = [];
|
|
64
|
-
if (!existsSync(dir)) return results;
|
|
65
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
66
|
-
for (const entry of entries) {
|
|
67
|
-
if (entry.isFile() && entry.name.endsWith('.json')) {
|
|
68
|
-
results.push(prefix ? `${prefix}/${entry.name}` : entry.name);
|
|
69
|
-
} else if (entry.isDirectory()) {
|
|
70
|
-
results.push(...scanJSONFiles(join(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return results;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function isCMSPage(pageData: JSONPage): boolean {
|
|
77
|
-
return pageData.meta?.source === 'cms' && !!pageData.meta?.cms;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Flatten a CMS item for the Webflow emit path: resolve i18n values to the
|
|
82
|
-
* current locale and unwrap rich-text markers (`{ __richtext__, html }`) into
|
|
83
|
-
* `RAW_HTML_PREFIX + html` so `nodeToWebflow`'s `resolveTemplate` can flatten
|
|
84
|
-
* inline HTML to plain text. Mirrors what SSR's `processCMSTemplate`
|
|
85
|
-
* (`cmsSSRProcessor.ts`) does inline at every interpolation site — but applied
|
|
86
|
-
* once up front so the simpler Webflow `resolveTemplate` (which only does
|
|
87
|
-
* `String(value)`) renders meaningful text instead of `[object Object]` /
|
|
88
|
-
* empty strings.
|
|
89
|
-
*/
|
|
90
|
-
function flattenCMSItemForLocale(
|
|
91
|
-
item: CMSItem,
|
|
92
|
-
locale: string,
|
|
93
|
-
i18nConfig: I18nConfig
|
|
94
|
-
): Record<string, unknown> {
|
|
95
|
-
const flatten = (value: unknown): unknown => {
|
|
96
|
-
if (value === null || value === undefined) return value;
|
|
97
|
-
if (isI18nValue(value)) {
|
|
98
|
-
return flatten(resolveI18nValue(value, locale, i18nConfig));
|
|
99
|
-
}
|
|
100
|
-
if (typeof value === 'object' && '__richtext__' in (value as object)) {
|
|
101
|
-
const html = (value as { html?: unknown }).html;
|
|
102
|
-
if (typeof html === 'string') return RAW_HTML_PREFIX + html;
|
|
103
|
-
}
|
|
104
|
-
return value;
|
|
105
|
-
};
|
|
106
|
-
const out: Record<string, unknown> = {};
|
|
107
|
-
for (const [key, value] of Object.entries(item)) {
|
|
108
|
-
out[key] = flatten(value);
|
|
109
|
-
}
|
|
110
|
-
return out;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Resolve a page-meta value (which may be an i18n object) to a string for the
|
|
115
|
-
* given locale, or undefined when the field is empty.
|
|
116
|
-
*/
|
|
117
|
-
function resolveMetaString(
|
|
118
|
-
value: unknown,
|
|
119
|
-
locale: string,
|
|
120
|
-
i18nConfig: I18nConfig
|
|
121
|
-
): string | undefined {
|
|
122
|
-
if (value === undefined || value === null || value === '') return undefined;
|
|
123
|
-
const resolved = isI18nValue(value)
|
|
124
|
-
? resolveI18nValue(value, locale, i18nConfig)
|
|
125
|
-
: value;
|
|
126
|
-
if (resolved === undefined || resolved === null || resolved === '') return undefined;
|
|
127
|
-
return String(resolved);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Lift the structured meta from a page (title, description, OG fields,
|
|
132
|
-
* keywords) into the per-locale fields of a `WebflowPage`. SSR's `result.title`
|
|
133
|
-
* is preserved as the canonical title; the rest comes from `extractPageMeta`.
|
|
134
|
-
*/
|
|
135
|
-
function buildPageMetaForLocale(
|
|
136
|
-
meta: PageMeta,
|
|
137
|
-
locale: string,
|
|
138
|
-
i18nConfig: I18nConfig
|
|
139
|
-
): Pick<WebflowPage, 'description' | 'keywords' | 'ogTitle' | 'ogDescription' | 'ogImage'> {
|
|
140
|
-
return {
|
|
141
|
-
description: resolveMetaString(meta.description, locale, i18nConfig),
|
|
142
|
-
keywords: resolveMetaString(meta.keywords, locale, i18nConfig),
|
|
143
|
-
ogTitle: resolveMetaString(meta.ogTitle, locale, i18nConfig),
|
|
144
|
-
ogDescription: resolveMetaString(meta.ogDescription, locale, i18nConfig),
|
|
145
|
-
ogImage: resolveMetaString(meta.ogImage, locale, i18nConfig),
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function scanAssets(projectRoot: string): WebflowAssetRef[] {
|
|
150
|
-
const assets: WebflowAssetRef[] = [];
|
|
151
|
-
const assetDirs: Array<{ dir: string; type: WebflowAssetRef['type'] }> = [
|
|
152
|
-
{ dir: 'images', type: 'image' },
|
|
153
|
-
{ dir: 'fonts', type: 'font' },
|
|
154
|
-
{ dir: 'videos', type: 'video' },
|
|
155
|
-
{ dir: 'assets', type: 'file' },
|
|
156
|
-
];
|
|
157
|
-
|
|
158
|
-
for (const { dir, type } of assetDirs) {
|
|
159
|
-
const fullDir = join(projectRoot, dir);
|
|
160
|
-
if (!existsSync(fullDir)) continue;
|
|
161
|
-
const files = scanJSONFiles(fullDir).map(f => f.replace('.json', '')); // scanJSONFiles works for any extension
|
|
162
|
-
// Re-scan properly for all file types
|
|
163
|
-
const allFiles = scanAllFiles(fullDir);
|
|
164
|
-
for (const file of allFiles) {
|
|
165
|
-
assets.push({
|
|
166
|
-
localPath: `${dir}/${file}`,
|
|
167
|
-
type,
|
|
168
|
-
fileName: file.split('/').pop()!,
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return assets;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function scanAllFiles(dir: string, prefix: string = ''): string[] {
|
|
177
|
-
const results: string[] = [];
|
|
178
|
-
if (!existsSync(dir)) return results;
|
|
179
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
180
|
-
for (const entry of entries) {
|
|
181
|
-
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
182
|
-
if (entry.isFile()) {
|
|
183
|
-
results.push(relativePath);
|
|
184
|
-
} else if (entry.isDirectory()) {
|
|
185
|
-
results.push(...scanAllFiles(join(dir, entry.name), relativePath));
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return results;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Build per-theme `--var` maps so the walker can resolve `var(--bg)` against
|
|
193
|
-
* whatever theme an element actually inherits. Each theme key holds its full
|
|
194
|
-
* resolved palette (text, bg, border, …); `defaultThemeName` is what we fall
|
|
195
|
-
* back to when an element has no `theme` ancestor.
|
|
196
|
-
*/
|
|
197
|
-
function buildThemeVarMaps(
|
|
198
|
-
themeConfig: ThemeConfig
|
|
199
|
-
): { byTheme: Record<string, Record<string, string>>; defaultTheme: string } {
|
|
200
|
-
const palette = themeConfig.palette;
|
|
201
|
-
const byTheme: Record<string, Record<string, string>> = {};
|
|
202
|
-
for (const [themeName, theme] of Object.entries(themeConfig.themes)) {
|
|
203
|
-
const vars: Record<string, string> = {};
|
|
204
|
-
for (const [name, value] of Object.entries(theme.colors)) {
|
|
205
|
-
vars[`--${name}`] = resolvePaletteColor(value, palette);
|
|
206
|
-
}
|
|
207
|
-
byTheme[themeName] = vars;
|
|
208
|
-
}
|
|
209
|
-
return { byTheme, defaultTheme: themeConfig.default };
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Build a per-breakpoint `--var → value` map directly from the variables
|
|
214
|
-
* config. Each breakpoint key (`base`, `tablet`, `mobile`, …) holds the full
|
|
215
|
-
* resolved variable map at that breakpoint, with per-variable `scales`
|
|
216
|
-
* overrides and global category scaling already applied
|
|
217
|
-
* (`resolveVariableValueAtBreakpoint` mirrors `generateVariablesCSS` and the
|
|
218
|
-
* runtime CSS resolver).
|
|
219
|
-
*
|
|
220
|
-
* The walker uses these maps to inline `var(--x)` references in element
|
|
221
|
-
* styles per-breakpoint, so the Webflow class system receives concrete
|
|
222
|
-
* scaled values at every tier instead of a single flat base value.
|
|
223
|
-
*/
|
|
224
|
-
function buildProjectVarMaps(
|
|
225
|
-
variablesConfig: VariablesConfig,
|
|
226
|
-
breakpoints: BreakpointConfig,
|
|
227
|
-
responsiveScales: ResponsiveScales | undefined
|
|
228
|
-
): Record<string, Record<string, string>> {
|
|
229
|
-
const out: Record<string, Record<string, string>> = { base: {} };
|
|
230
|
-
for (const bpName of Object.keys(breakpoints)) out[bpName] = {};
|
|
231
|
-
|
|
232
|
-
for (const variable of variablesConfig.variables) {
|
|
233
|
-
if (!variable.cssVar) continue;
|
|
234
|
-
out.base[variable.cssVar] = variable.value;
|
|
235
|
-
for (const bpName of Object.keys(breakpoints)) {
|
|
236
|
-
const resolved = resolveVariableValueAtBreakpoint(
|
|
237
|
-
{ value: variable.value, type: variable.type, scales: variable.scales },
|
|
238
|
-
bpName,
|
|
239
|
-
responsiveScales
|
|
240
|
-
);
|
|
241
|
-
out[bpName][variable.cssVar] = resolved;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return out;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// ---------------------------------------------------------------------------
|
|
248
|
-
// Main export
|
|
249
|
-
// ---------------------------------------------------------------------------
|
|
250
|
-
|
|
251
|
-
export async function buildWebflowPayload(
|
|
252
|
-
options?: { bindCollectionLists?: boolean; promotedComponentNames?: string[]; locale?: string }
|
|
253
|
-
): Promise<WebflowExportPayload> {
|
|
254
|
-
const bindCollectionLists = options?.bindCollectionLists === true;
|
|
255
|
-
const promotedComponentNames = Array.isArray(options?.promotedComponentNames)
|
|
256
|
-
? new Set(options!.promotedComponentNames.filter((n): n is string => typeof n === 'string' && n.length > 0))
|
|
257
|
-
: undefined;
|
|
258
|
-
// 1. Setup: load project configuration
|
|
259
|
-
configService.reset();
|
|
260
|
-
|
|
261
|
-
const projectConfig = await loadProjectConfig();
|
|
262
|
-
const siteUrl = (projectConfig as { siteUrl?: string }).siteUrl?.replace(/\/$/, '') || '';
|
|
263
|
-
const i18nConfig = await loadI18nConfig();
|
|
264
|
-
|
|
265
|
-
// Pick which locale to render. Multi-locale projects export one locale at a
|
|
266
|
-
// time so the Webflow site mirrors a single language; the extension surfaces
|
|
267
|
-
// a picker that defaults to `i18nConfig.defaultLocale`. An invalid/missing
|
|
268
|
-
// request falls back to the default locale (silent — the picker is the
|
|
269
|
-
// source of truth here, not the URL).
|
|
270
|
-
const requestedLocale = options?.locale;
|
|
271
|
-
const selectedLocale = (requestedLocale && i18nConfig.locales.some(l => l.code === requestedLocale))
|
|
272
|
-
? requestedLocale
|
|
273
|
-
: i18nConfig.defaultLocale;
|
|
274
|
-
const localesToBuild = i18nConfig.locales.filter(l => l.code === selectedLocale);
|
|
275
|
-
|
|
276
|
-
await migrateTemplatesDirectory();
|
|
277
|
-
|
|
278
|
-
const { components } = await loadComponentDirectory(projectPaths.components());
|
|
279
|
-
const globalComponents: Record<string, ComponentDefinition> = {};
|
|
280
|
-
components.forEach((value, key) => { globalComponents[key] = value; });
|
|
281
|
-
|
|
282
|
-
const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());
|
|
283
|
-
const cmsService = new CMSService(cmsProvider);
|
|
284
|
-
await cmsService.initialize();
|
|
285
|
-
|
|
286
|
-
const themeConfig = await colorService.loadThemeConfig();
|
|
287
|
-
const variablesConfig = await variableService.loadConfig();
|
|
288
|
-
const breakpoints = await loadBreakpointConfig();
|
|
289
|
-
|
|
290
|
-
await configService.load();
|
|
291
|
-
const responsiveScales = configService.getResponsiveScales();
|
|
292
|
-
|
|
293
|
-
// 2. Scan pages
|
|
294
|
-
const pagesDir = projectPaths.pages();
|
|
295
|
-
if (!existsSync(pagesDir)) {
|
|
296
|
-
return emptyPayload();
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const pageFiles = scanJSONFiles(pagesDir);
|
|
300
|
-
if (pageFiles.length === 0) {
|
|
301
|
-
return emptyPayload();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Collect slug mappings
|
|
305
|
-
const slugMappings: SlugMap[] = [];
|
|
306
|
-
for (const file of pageFiles) {
|
|
307
|
-
const pageName = file.replace('.json', '');
|
|
308
|
-
const basePath = mapPageNameToPath(pageName);
|
|
309
|
-
const pageContent = await loadJSONFile(join(pagesDir, file));
|
|
310
|
-
if (!pageContent) continue;
|
|
311
|
-
try {
|
|
312
|
-
const pageData = parseJSON<JSONPage>(pageContent);
|
|
313
|
-
if (pageData.meta?.slugs) {
|
|
314
|
-
const pageId = basePath === '/' ? 'index' : basePath.substring(1);
|
|
315
|
-
slugMappings.push({ pageId, slugs: pageData.meta.slugs });
|
|
316
|
-
}
|
|
317
|
-
} catch { /* ignore */ }
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// 3. Render and convert pages
|
|
321
|
-
const allPages: WebflowPage[] = [];
|
|
322
|
-
const allStyleClasses = new Map<string, WebflowStyleClass>();
|
|
323
|
-
// elementClass → interactiveStyles, populated during the node walk and
|
|
324
|
-
// drained at the end into raw CSS (see step 6 below).
|
|
325
|
-
const allInteractiveStylesMap = new Map<string, InteractiveStyles>();
|
|
326
|
-
// Combo class name → owning identity, shared across every page emit so
|
|
327
|
-
// collisions are visible project-wide. Drives `mintInstanceComboName` in
|
|
328
|
-
// nodeToWebflow.ts.
|
|
329
|
-
const allComboIdentityByName = new Map<string, string>();
|
|
330
|
-
// First-encounter snapshot of each promoted component (Navigation, Footer)
|
|
331
|
-
// shared across every page so the extension registers each definition once.
|
|
332
|
-
const promotedComponents = new Map<string, WebflowComponentDef>();
|
|
333
|
-
|
|
334
|
-
// Theme + project-level CSS variables are resolved during the walk so the
|
|
335
|
-
// ancestor `theme` attribute can pick the right palette per element. The
|
|
336
|
-
// project var map is per-breakpoint so `var(--x)` refs in element styles
|
|
337
|
-
// can be inlined at each tier with the right scaled value.
|
|
338
|
-
const variablesCSS = generateVariablesCSS(variablesConfig, breakpoints, responsiveScales);
|
|
339
|
-
const projectVars = buildProjectVarMaps(variablesConfig, breakpoints, responsiveScales);
|
|
340
|
-
const { byTheme: themeVars, defaultTheme } = buildThemeVarMaps(themeConfig);
|
|
341
|
-
|
|
342
|
-
// Regular pages
|
|
343
|
-
for (const file of pageFiles) {
|
|
344
|
-
const pageName = file.replace('.json', '');
|
|
345
|
-
const basePath = mapPageNameToPath(pageName);
|
|
346
|
-
const pageContent = await loadJSONFile(join(pagesDir, file));
|
|
347
|
-
if (!pageContent) continue;
|
|
348
|
-
|
|
349
|
-
try {
|
|
350
|
-
const pageData = parseJSON<JSONPage>(pageContent);
|
|
351
|
-
if (pageData.meta?.draft === true) continue;
|
|
352
|
-
|
|
353
|
-
const slugs = pageData.meta?.slugs;
|
|
354
|
-
|
|
355
|
-
for (const localeConfig of localesToBuild) {
|
|
356
|
-
const locale = localeConfig.code;
|
|
357
|
-
const isDefault = locale === i18nConfig.defaultLocale;
|
|
358
|
-
|
|
359
|
-
let slug: string;
|
|
360
|
-
if (slugs && slugs[locale]) {
|
|
361
|
-
slug = slugs[locale];
|
|
362
|
-
} else if (basePath === '/') {
|
|
363
|
-
slug = '';
|
|
364
|
-
} else {
|
|
365
|
-
slug = basePath.substring(1);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
const urlPath = isDefault
|
|
369
|
-
? (slug === '' ? '/' : `/${slug}`)
|
|
370
|
-
: (slug === '' ? `/${locale}` : `/${locale}/${slug}`);
|
|
371
|
-
|
|
372
|
-
// Render via SSR to resolve all props
|
|
373
|
-
const result = await renderPageSSR(
|
|
374
|
-
pageData,
|
|
375
|
-
globalComponents,
|
|
376
|
-
urlPath,
|
|
377
|
-
siteUrl,
|
|
378
|
-
locale,
|
|
379
|
-
i18nConfig,
|
|
380
|
-
slugMappings,
|
|
381
|
-
undefined,
|
|
382
|
-
cmsService,
|
|
383
|
-
true
|
|
384
|
-
);
|
|
385
|
-
|
|
386
|
-
// Convert node tree to Webflow elements
|
|
387
|
-
const ctx: WebflowEmitContext = {
|
|
388
|
-
globalComponents,
|
|
389
|
-
elementPath: [0],
|
|
390
|
-
fileType: 'page',
|
|
391
|
-
fileName: pageName,
|
|
392
|
-
breakpoints,
|
|
393
|
-
styleClasses: allStyleClasses,
|
|
394
|
-
comboIdentityByName: allComboIdentityByName,
|
|
395
|
-
interactiveStylesMap: allInteractiveStylesMap,
|
|
396
|
-
cmsService,
|
|
397
|
-
i18nConfig,
|
|
398
|
-
locale,
|
|
399
|
-
slugMappings,
|
|
400
|
-
pagePath: urlPath,
|
|
401
|
-
themeVars,
|
|
402
|
-
projectVars,
|
|
403
|
-
defaultTheme,
|
|
404
|
-
responsiveScales,
|
|
405
|
-
promotedComponents,
|
|
406
|
-
promotedComponentNames,
|
|
407
|
-
bindCollectionLists,
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
const body = pageData.root || (pageData as any).node;
|
|
411
|
-
const elements = body ? await nodeToWebflow(body, ctx) : [];
|
|
412
|
-
normalizeListChildren(elements);
|
|
413
|
-
|
|
414
|
-
const pageMeta = extractPageMeta(pageData);
|
|
415
|
-
allPages.push({
|
|
416
|
-
title: result.title,
|
|
417
|
-
slug: slug || 'index',
|
|
418
|
-
elements,
|
|
419
|
-
locale,
|
|
420
|
-
...buildPageMetaForLocale(pageMeta, locale, i18nConfig),
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
} catch (error: any) {
|
|
424
|
-
console.error(`Error processing ${basePath}:`, error?.message);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// CMS template pages — imported as a single regular Webflow page per locale,
|
|
429
|
-
// bound to the FIRST CMS item's content. Webflow can't natively bind a page
|
|
430
|
-
// to a Meno-side collection, and a separate "Sync CMS" flow in the extension
|
|
431
|
-
// handles collection schema/items, so this code path stays page-only.
|
|
432
|
-
const templatesDir = projectPaths.templates();
|
|
433
|
-
|
|
434
|
-
if (existsSync(templatesDir)) {
|
|
435
|
-
const templateFiles = readdirSync(templatesDir).filter(f => f.endsWith('.json'));
|
|
436
|
-
|
|
437
|
-
for (const file of templateFiles) {
|
|
438
|
-
const templateContent = await loadJSONFile(join(templatesDir, file));
|
|
439
|
-
if (!templateContent) continue;
|
|
440
|
-
|
|
441
|
-
try {
|
|
442
|
-
const pageData = parseJSON<JSONPage>(templateContent);
|
|
443
|
-
if (pageData.meta?.draft === true) continue;
|
|
444
|
-
if (!isCMSPage(pageData)) continue;
|
|
445
|
-
|
|
446
|
-
const cmsSchema = pageData.meta!.cms as CMSSchema;
|
|
447
|
-
const items = await cmsService.queryItems({ collection: cmsSchema.id });
|
|
448
|
-
if (items.length === 0) continue;
|
|
449
|
-
|
|
450
|
-
const item = items[0];
|
|
451
|
-
const pageName = file.replace('.json', '');
|
|
452
|
-
|
|
453
|
-
for (const localeConfig of localesToBuild) {
|
|
454
|
-
const locale = localeConfig.code;
|
|
455
|
-
// Use the first item's resolved URL (from cmsSchema.urlPattern) as
|
|
456
|
-
// the slug, so a template like `templates/blog.json` lands at
|
|
457
|
-
// `/blog/<first-slug>` and doesn't collide with a sibling listing
|
|
458
|
-
// page like `pages/blog.json`.
|
|
459
|
-
let itemSlug = item[cmsSchema.slugField] ?? item._slug ?? item._filename ?? item._id;
|
|
460
|
-
if (isI18nValue(itemSlug)) {
|
|
461
|
-
itemSlug = resolveI18nValue(itemSlug, locale, i18nConfig) as string;
|
|
462
|
-
}
|
|
463
|
-
const resolvedItemPath = cmsSchema.urlPattern.replace('{{slug}}', String(itemSlug));
|
|
464
|
-
const isDefault = locale === i18nConfig.defaultLocale;
|
|
465
|
-
const localizedItemPath = isDefault
|
|
466
|
-
? resolvedItemPath
|
|
467
|
-
: `/${locale}${resolvedItemPath.startsWith('/') ? '' : '/'}${resolvedItemPath}`;
|
|
468
|
-
const slug = localizedItemPath.startsWith('/')
|
|
469
|
-
? localizedItemPath.substring(1)
|
|
470
|
-
: localizedItemPath;
|
|
471
|
-
const urlPath = localizedItemPath;
|
|
472
|
-
// SSR (`renderPageSSR`) gets the raw item — its `processCMSTemplate`
|
|
473
|
-
// resolves i18n + richtext at each interpolation. The Webflow path
|
|
474
|
-
// re-walks the same `pageData.root` with the simpler `resolveTemplate`
|
|
475
|
-
// (no i18n / richtext awareness), so we hand it a pre-flattened item.
|
|
476
|
-
const flatItem = flattenCMSItemForLocale(item, locale, i18nConfig);
|
|
477
|
-
const itemWithUrl: CMSItem = { ...flatItem, _url: urlPath } as CMSItem;
|
|
478
|
-
const ssrItem: CMSItem = { ...item, _url: urlPath };
|
|
479
|
-
|
|
480
|
-
const result = await renderPageSSR(
|
|
481
|
-
pageData,
|
|
482
|
-
globalComponents,
|
|
483
|
-
urlPath,
|
|
484
|
-
siteUrl,
|
|
485
|
-
locale,
|
|
486
|
-
i18nConfig,
|
|
487
|
-
slugMappings,
|
|
488
|
-
{ cms: ssrItem },
|
|
489
|
-
cmsService,
|
|
490
|
-
true
|
|
491
|
-
);
|
|
492
|
-
|
|
493
|
-
const ctx: WebflowEmitContext = {
|
|
494
|
-
globalComponents,
|
|
495
|
-
elementPath: [0],
|
|
496
|
-
fileType: 'page',
|
|
497
|
-
fileName: pageName,
|
|
498
|
-
breakpoints,
|
|
499
|
-
styleClasses: allStyleClasses,
|
|
500
|
-
comboIdentityByName: allComboIdentityByName,
|
|
501
|
-
interactiveStylesMap: allInteractiveStylesMap,
|
|
502
|
-
cmsService,
|
|
503
|
-
i18nConfig,
|
|
504
|
-
locale,
|
|
505
|
-
slugMappings,
|
|
506
|
-
pagePath: urlPath,
|
|
507
|
-
cmsContext: { cms: itemWithUrl },
|
|
508
|
-
// Seed `templateContext` with the bound item so descendants inside
|
|
509
|
-
// a component slot still see `cms`. `emitInlineComponentBody`
|
|
510
|
-
// merges `ctx.templateContext` into the body's `instanceProps`
|
|
511
|
-
// (nodeToWebflow.ts:1140-1143), and `<slot>` rendering forwards
|
|
512
|
-
// those merged props to slot children — without this, anything
|
|
513
|
-
// wrapped in (e.g.) Section loses the page-level CMS scope and
|
|
514
|
-
// `{{cms.title}}` resolves to empty.
|
|
515
|
-
templateContext: { cms: itemWithUrl } as Record<string, unknown>,
|
|
516
|
-
themeVars,
|
|
517
|
-
projectVars,
|
|
518
|
-
defaultTheme,
|
|
519
|
-
responsiveScales,
|
|
520
|
-
promotedComponents,
|
|
521
|
-
promotedComponentNames,
|
|
522
|
-
bindCollectionLists,
|
|
523
|
-
};
|
|
524
|
-
|
|
525
|
-
const body = pageData.root || (pageData as any).node;
|
|
526
|
-
const elements = body ? await nodeToWebflow(body, ctx, { cms: itemWithUrl }) : [];
|
|
527
|
-
normalizeListChildren(elements);
|
|
528
|
-
|
|
529
|
-
const cmsPageMeta = extractPageMeta(pageData);
|
|
530
|
-
allPages.push({
|
|
531
|
-
title: result.title,
|
|
532
|
-
slug,
|
|
533
|
-
elements,
|
|
534
|
-
locale,
|
|
535
|
-
...buildPageMetaForLocale(cmsPageMeta, locale, i18nConfig),
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
} catch (error: any) {
|
|
539
|
-
console.error(`Error processing template ${file}:`, error?.message);
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// Promoted components (Navigation, Footer) are emitted via the same
|
|
545
|
-
// `nodeToWebflow` walk as pages, so they share the same `<ul>`-with-
|
|
546
|
-
// non-`<li>`-children pitfall. Normalize their element trees too before
|
|
547
|
-
// they leave the build.
|
|
548
|
-
for (const def of promotedComponents.values()) {
|
|
549
|
-
normalizeListChildren(def.elements);
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
// 4. Scan assets
|
|
553
|
-
const styleClasses = Array.from(allStyleClasses.values());
|
|
554
|
-
const assets = scanAssets(projectPaths.project);
|
|
555
|
-
|
|
556
|
-
// 5. Collect component scripts and component-scoped CSS sidecars. Both get
|
|
557
|
-
// bundled into the manual-paste UI: scripts as a `<script>` at body end,
|
|
558
|
-
// CSS as part of the `<style>` block at head. CSS in particular is
|
|
559
|
-
// critical for components that drive visibility through hand-written
|
|
560
|
-
// rules (e.g. NavDropdown's `[data-nav-dropdown="container"].open ...`)
|
|
561
|
-
// — those don't translate to Webflow's class system at all.
|
|
562
|
-
const scripts: WebflowScript[] = [];
|
|
563
|
-
const cssBlocks: string[] = [];
|
|
564
|
-
for (const [name, def] of Object.entries(globalComponents)) {
|
|
565
|
-
const code = def.component?.javascript;
|
|
566
|
-
if (typeof code === 'string' && code.trim().length > 0) {
|
|
567
|
-
scripts.push({
|
|
568
|
-
componentName: name,
|
|
569
|
-
code,
|
|
570
|
-
defineVars: def.component?.defineVars,
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
const css = def.component?.css;
|
|
574
|
-
if (typeof css === 'string' && css.trim().length > 0) {
|
|
575
|
-
cssBlocks.push(`/* ${name}.css */\n${css.trim()}`);
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
const componentCss = cssBlocks.length > 0 ? cssBlocks.join('\n\n') : undefined;
|
|
579
|
-
|
|
580
|
-
// 6. Per-element interactiveStyles → raw CSS for rules Webflow's class
|
|
581
|
-
// system can't represent (anything with `prefix`, class-style postfix,
|
|
582
|
-
// or breakpoint-divided pseudos). Pseudo-only rules with empty prefix
|
|
583
|
-
// have already been written into `primaryClass.pseudoStates` upstream
|
|
584
|
-
// via `Style.setProperties({ pseudo })`; we filter those out here so
|
|
585
|
-
// the bundle doesn't double-emit them.
|
|
586
|
-
const interactiveCssBlocks: string[] = [];
|
|
587
|
-
for (const [elementClass, rules] of allInteractiveStylesMap) {
|
|
588
|
-
const customRules = rules.filter((r) => !isWebflowHandledRule(r));
|
|
589
|
-
if (customRules.length === 0) continue;
|
|
590
|
-
const css = generateInteractiveCSS(elementClass, customRules, breakpoints, undefined, responsiveScales);
|
|
591
|
-
if (css && css.trim().length > 0) {
|
|
592
|
-
interactiveCssBlocks.push(css);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
const interactiveCss = interactiveCssBlocks.length > 0
|
|
596
|
-
? interactiveCssBlocks.join('\n\n')
|
|
597
|
-
: undefined;
|
|
598
|
-
|
|
599
|
-
return {
|
|
600
|
-
version: 1,
|
|
601
|
-
exportedAt: new Date().toISOString(),
|
|
602
|
-
pages: allPages,
|
|
603
|
-
styles: styleClasses,
|
|
604
|
-
cms: [],
|
|
605
|
-
assets,
|
|
606
|
-
slugMappings: slugMappings.length > 0 ? slugMappings : undefined,
|
|
607
|
-
scripts: scripts.length > 0 ? scripts : undefined,
|
|
608
|
-
components: promotedComponents.size > 0
|
|
609
|
-
? Array.from(promotedComponents.values())
|
|
610
|
-
: undefined,
|
|
611
|
-
componentCss,
|
|
612
|
-
interactiveCss,
|
|
613
|
-
i18n: {
|
|
614
|
-
defaultLocale: i18nConfig.defaultLocale,
|
|
615
|
-
locales: i18nConfig.locales.map(l => ({
|
|
616
|
-
code: l.code,
|
|
617
|
-
name: l.name,
|
|
618
|
-
nativeName: l.nativeName,
|
|
619
|
-
})),
|
|
620
|
-
selectedLocale,
|
|
621
|
-
},
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
function emptyPayload(): WebflowExportPayload {
|
|
626
|
-
return {
|
|
627
|
-
version: 1,
|
|
628
|
-
exportedAt: new Date().toISOString(),
|
|
629
|
-
pages: [],
|
|
630
|
-
styles: [],
|
|
631
|
-
cms: [],
|
|
632
|
-
assets: [],
|
|
633
|
-
};
|
|
634
|
-
}
|
|
635
|
-
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Webflow Export Module
|
|
3
|
-
* Re-exports the main build function and types.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export { buildWebflowPayload } from './buildWebflow';
|
|
7
|
-
export { nodeToWebflow } from './nodeToWebflow';
|
|
8
|
-
export { mapStylesToWebflow } from './styleMapper';
|
|
9
|
-
export { wrapInWebflowTemplate } from './templateWrapper';
|
|
10
|
-
export type {
|
|
11
|
-
WebflowExportPayload,
|
|
12
|
-
WebflowPage,
|
|
13
|
-
WebflowElement,
|
|
14
|
-
WebflowStyleClass,
|
|
15
|
-
WebflowCMSCollection,
|
|
16
|
-
WebflowCMSField,
|
|
17
|
-
WebflowAssetRef,
|
|
18
|
-
WebflowBreakpoint,
|
|
19
|
-
WebflowPseudoState,
|
|
20
|
-
WebflowFieldType,
|
|
21
|
-
CSSProperties,
|
|
22
|
-
} from './types';
|
|
23
|
-
export { mapCMSFieldType } from './types';
|