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,1136 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CMSService,
|
|
3
|
-
FileSystemCMSProvider,
|
|
4
|
-
clearJSValidationCache,
|
|
5
|
-
generateSSRHTML,
|
|
6
|
-
getJSValidationErrors,
|
|
7
|
-
loadComponentDirectory,
|
|
8
|
-
loadI18nConfig,
|
|
9
|
-
loadJSONFile,
|
|
10
|
-
loadProjectConfig,
|
|
11
|
-
mapPageNameToPath,
|
|
12
|
-
migrateTemplatesDirectory,
|
|
13
|
-
parseJSON,
|
|
14
|
-
prepareClientData
|
|
15
|
-
} from "./chunk-IGYR22T6.js";
|
|
16
|
-
import {
|
|
17
|
-
minifyJS,
|
|
18
|
-
projectPaths
|
|
19
|
-
} from "./chunk-I7YIGZXT.js";
|
|
20
|
-
import {
|
|
21
|
-
inspect
|
|
22
|
-
} from "./chunk-WQFG7PAH.js";
|
|
23
|
-
import {
|
|
24
|
-
collectComponentLibraries,
|
|
25
|
-
extractLibraryOrigins,
|
|
26
|
-
filterLibrariesByContext
|
|
27
|
-
} from "./chunk-X754AHS5.js";
|
|
28
|
-
import {
|
|
29
|
-
isItemDraftForLocale,
|
|
30
|
-
isItemFullyPublished
|
|
31
|
-
} from "./chunk-JGWFTO6P.js";
|
|
32
|
-
import {
|
|
33
|
-
isI18nValue,
|
|
34
|
-
resolveI18nValue
|
|
35
|
-
} from "./chunk-AZQYF6KE.js";
|
|
36
|
-
|
|
37
|
-
// build-static.ts
|
|
38
|
-
import { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync, unlinkSync, writeFileSync } from "fs";
|
|
39
|
-
import { writeFile, readFile } from "fs/promises";
|
|
40
|
-
import { join } from "path";
|
|
41
|
-
import { createHash } from "crypto";
|
|
42
|
-
|
|
43
|
-
// lib/server/ab/generateFunctions.ts
|
|
44
|
-
function generateMiddleware(experiments) {
|
|
45
|
-
const running = experiments.filter((e) => e.status === "running");
|
|
46
|
-
if (running.length === 0) return "";
|
|
47
|
-
const configJSON = JSON.stringify(running.map((e) => ({
|
|
48
|
-
id: e.id,
|
|
49
|
-
controlBranch: e.controlBranch,
|
|
50
|
-
controlWeight: e.controlWeight,
|
|
51
|
-
variants: e.variants.map((v) => ({
|
|
52
|
-
branch: v.branch,
|
|
53
|
-
weight: v.weight,
|
|
54
|
-
deployUrl: v.deployUrl
|
|
55
|
-
}))
|
|
56
|
-
})));
|
|
57
|
-
return `/**
|
|
58
|
-
* A/B Testing Traffic Splitting Middleware
|
|
59
|
-
* Auto-generated by Meno build - do not edit manually
|
|
60
|
-
*/
|
|
61
|
-
|
|
62
|
-
interface Env {
|
|
63
|
-
AB_DB?: D1Database;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
interface ExperimentConfig {
|
|
67
|
-
id: string;
|
|
68
|
-
controlBranch: string;
|
|
69
|
-
controlWeight: number;
|
|
70
|
-
variants: Array<{ branch: string; weight: number; deployUrl: string }>;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const EXPERIMENTS: ExperimentConfig[] = ${configJSON};
|
|
74
|
-
|
|
75
|
-
function getCookie(request: Request, name: string): string | null {
|
|
76
|
-
const cookieHeader = request.headers.get('Cookie');
|
|
77
|
-
if (!cookieHeader) return null;
|
|
78
|
-
const match = cookieHeader.match(new RegExp('(?:^|;\\\\s*)' + name + '=([^;]*)'));
|
|
79
|
-
return match ? decodeURIComponent(match[1]) : null;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function assignVariant(experiment: ExperimentConfig): string {
|
|
83
|
-
const rand = Math.random() * 100;
|
|
84
|
-
let cumulative = experiment.controlWeight;
|
|
85
|
-
if (rand < cumulative) return 'control';
|
|
86
|
-
for (const variant of experiment.variants) {
|
|
87
|
-
cumulative += variant.weight;
|
|
88
|
-
if (rand < cumulative) return variant.branch;
|
|
89
|
-
}
|
|
90
|
-
return 'control';
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function onRequest(context: { request: Request; next: () => Promise<Response>; env: Env }) {
|
|
94
|
-
const url = new URL(context.request.url);
|
|
95
|
-
|
|
96
|
-
// Skip API routes and static assets
|
|
97
|
-
if (url.pathname.startsWith('/api/') || url.pathname.match(/\\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/)) {
|
|
98
|
-
return context.next();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Use first running experiment (single experiment at a time for simplicity)
|
|
102
|
-
const experiment = EXPERIMENTS[0];
|
|
103
|
-
if (!experiment) return context.next();
|
|
104
|
-
|
|
105
|
-
// Check for existing variant assignment (sticky sessions)
|
|
106
|
-
let variant = getCookie(context.request, 'meno_variant');
|
|
107
|
-
|
|
108
|
-
// If no cookie, assign a variant
|
|
109
|
-
if (!variant) {
|
|
110
|
-
variant = assignVariant(experiment);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
let response: Response;
|
|
114
|
-
|
|
115
|
-
if (variant === 'control') {
|
|
116
|
-
// Control: serve local assets (pass through)
|
|
117
|
-
response = await context.next();
|
|
118
|
-
} else {
|
|
119
|
-
// Variant: proxy to branch preview deploy
|
|
120
|
-
const variantConfig = experiment.variants.find(v => v.branch === variant);
|
|
121
|
-
if (!variantConfig) {
|
|
122
|
-
response = await context.next();
|
|
123
|
-
} else {
|
|
124
|
-
// Fetch from the variant's deploy URL
|
|
125
|
-
const variantUrl = new URL(url.pathname + url.search, variantConfig.deployUrl);
|
|
126
|
-
try {
|
|
127
|
-
const proxyResponse = await fetch(variantUrl.toString(), {
|
|
128
|
-
method: context.request.method,
|
|
129
|
-
headers: context.request.headers,
|
|
130
|
-
});
|
|
131
|
-
response = new Response(proxyResponse.body, {
|
|
132
|
-
status: proxyResponse.status,
|
|
133
|
-
statusText: proxyResponse.statusText,
|
|
134
|
-
headers: new Headers(proxyResponse.headers),
|
|
135
|
-
});
|
|
136
|
-
} catch {
|
|
137
|
-
// Fallback to control if variant fetch fails
|
|
138
|
-
response = await context.next();
|
|
139
|
-
variant = 'control';
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Set variant cookie (30-day expiry)
|
|
145
|
-
const headers = new Headers(response.headers);
|
|
146
|
-
headers.append(
|
|
147
|
-
'Set-Cookie',
|
|
148
|
-
\`meno_variant=\${encodeURIComponent(variant!)}; Path=/; Max-Age=2592000; SameSite=Lax\`
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
return new Response(response.body, {
|
|
152
|
-
status: response.status,
|
|
153
|
-
statusText: response.statusText,
|
|
154
|
-
headers,
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
`;
|
|
158
|
-
}
|
|
159
|
-
function generateTrackFunction() {
|
|
160
|
-
return `/**
|
|
161
|
-
* A/B Testing Event Tracker
|
|
162
|
-
* Auto-generated by Meno build - do not edit manually
|
|
163
|
-
* POST /api/ab-track - stores pageview/conversion events in D1
|
|
164
|
-
*/
|
|
165
|
-
|
|
166
|
-
interface Env {
|
|
167
|
-
AB_DB: D1Database;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
interface TrackEvent {
|
|
171
|
-
experimentId: string;
|
|
172
|
-
visitorId: string;
|
|
173
|
-
variant: string;
|
|
174
|
-
eventType: 'pageview' | 'conversion';
|
|
175
|
-
goalId?: string;
|
|
176
|
-
url?: string;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
interface PagesContext<E = unknown> {
|
|
180
|
-
request: Request;
|
|
181
|
-
env: E;
|
|
182
|
-
params: Record<string, string>;
|
|
183
|
-
waitUntil: (promise: Promise<unknown>) => void;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export async function onRequestPost(context: PagesContext<Env>): Promise<Response> {
|
|
187
|
-
try {
|
|
188
|
-
const body: TrackEvent = await context.request.json();
|
|
189
|
-
|
|
190
|
-
// Validate required fields
|
|
191
|
-
if (!body.experimentId || !body.visitorId || !body.variant || !body.eventType) {
|
|
192
|
-
return new Response(null, { status: 400 });
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Validate event type
|
|
196
|
-
if (body.eventType !== 'pageview' && body.eventType !== 'conversion') {
|
|
197
|
-
return new Response(null, { status: 400 });
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Insert event into D1
|
|
201
|
-
await context.env.AB_DB.prepare(
|
|
202
|
-
'INSERT INTO ab_events (experiment_id, visitor_id, variant, event_type, goal_id, url, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)'
|
|
203
|
-
).bind(
|
|
204
|
-
body.experimentId,
|
|
205
|
-
body.visitorId,
|
|
206
|
-
body.variant,
|
|
207
|
-
body.eventType,
|
|
208
|
-
body.goalId || null,
|
|
209
|
-
body.url || null,
|
|
210
|
-
Date.now()
|
|
211
|
-
).run();
|
|
212
|
-
|
|
213
|
-
return new Response(null, { status: 204 });
|
|
214
|
-
} catch {
|
|
215
|
-
return new Response(null, { status: 500 });
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
`;
|
|
219
|
-
}
|
|
220
|
-
function generateResultsFunction() {
|
|
221
|
-
return `/**
|
|
222
|
-
* A/B Testing Results API
|
|
223
|
-
* Auto-generated by Meno build - do not edit manually
|
|
224
|
-
* GET /api/ab-results?experiment=<id> - returns aggregated results with significance
|
|
225
|
-
*/
|
|
226
|
-
|
|
227
|
-
interface Env {
|
|
228
|
-
AB_DB: D1Database;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
interface PagesContext<E = unknown> {
|
|
232
|
-
request: Request;
|
|
233
|
-
env: E;
|
|
234
|
-
params: Record<string, string>;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
interface VariantResult {
|
|
238
|
-
variant: string;
|
|
239
|
-
visitors: number;
|
|
240
|
-
conversions: number;
|
|
241
|
-
conversionRate: number;
|
|
242
|
-
lift?: number;
|
|
243
|
-
pValue?: number;
|
|
244
|
-
isSignificant: boolean;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Two-proportion z-test for statistical significance
|
|
249
|
-
*/
|
|
250
|
-
function zTest(
|
|
251
|
-
conversionsA: number, visitorsA: number,
|
|
252
|
-
conversionsB: number, visitorsB: number
|
|
253
|
-
): number {
|
|
254
|
-
if (visitorsA === 0 || visitorsB === 0) return 1;
|
|
255
|
-
|
|
256
|
-
const pA = conversionsA / visitorsA;
|
|
257
|
-
const pB = conversionsB / visitorsB;
|
|
258
|
-
const pPool = (conversionsA + conversionsB) / (visitorsA + visitorsB);
|
|
259
|
-
|
|
260
|
-
if (pPool === 0 || pPool === 1) return 1;
|
|
261
|
-
|
|
262
|
-
const se = Math.sqrt(pPool * (1 - pPool) * (1 / visitorsA + 1 / visitorsB));
|
|
263
|
-
if (se === 0) return 1;
|
|
264
|
-
|
|
265
|
-
const z = Math.abs(pA - pB) / se;
|
|
266
|
-
|
|
267
|
-
// Approximate two-tailed p-value using rational approximation
|
|
268
|
-
const t = 1 / (1 + 0.2316419 * z);
|
|
269
|
-
const d = 0.3989422804014327;
|
|
270
|
-
const p = d * Math.exp(-z * z / 2) * t * (0.3193815 + t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));
|
|
271
|
-
return 2 * p;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
export async function onRequestGet(context: PagesContext<Env>): Promise<Response> {
|
|
275
|
-
const url = new URL(context.request.url);
|
|
276
|
-
const experimentId = url.searchParams.get('experiment');
|
|
277
|
-
|
|
278
|
-
if (!experimentId) {
|
|
279
|
-
return Response.json({ error: 'Missing experiment parameter' }, { status: 400 });
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
try {
|
|
283
|
-
// Get unique visitors per variant
|
|
284
|
-
const visitorsResult = await context.env.AB_DB.prepare(
|
|
285
|
-
'SELECT variant, COUNT(DISTINCT visitor_id) as visitors FROM ab_events WHERE experiment_id = ? AND event_type = \\'pageview\\' GROUP BY variant'
|
|
286
|
-
).bind(experimentId).all();
|
|
287
|
-
|
|
288
|
-
// Get conversions per variant
|
|
289
|
-
const conversionsResult = await context.env.AB_DB.prepare(
|
|
290
|
-
'SELECT variant, COUNT(DISTINCT visitor_id) as conversions FROM ab_events WHERE experiment_id = ? AND event_type = \\'conversion\\' GROUP BY variant'
|
|
291
|
-
).bind(experimentId).all();
|
|
292
|
-
|
|
293
|
-
// Build results map
|
|
294
|
-
const visitorMap = new Map<string, number>();
|
|
295
|
-
const conversionMap = new Map<string, number>();
|
|
296
|
-
|
|
297
|
-
for (const row of (visitorsResult.results || [])) {
|
|
298
|
-
visitorMap.set(row.variant as string, row.visitors as number);
|
|
299
|
-
}
|
|
300
|
-
for (const row of (conversionsResult.results || [])) {
|
|
301
|
-
conversionMap.set(row.variant as string, row.conversions as number);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Get all variant names
|
|
305
|
-
const allVariants = new Set([...visitorMap.keys(), ...conversionMap.keys()]);
|
|
306
|
-
|
|
307
|
-
// Calculate results
|
|
308
|
-
const variants: VariantResult[] = [];
|
|
309
|
-
let controlVisitors = 0;
|
|
310
|
-
let controlConversions = 0;
|
|
311
|
-
|
|
312
|
-
for (const variant of allVariants) {
|
|
313
|
-
const visitors = visitorMap.get(variant) || 0;
|
|
314
|
-
const conversions = conversionMap.get(variant) || 0;
|
|
315
|
-
const conversionRate = visitors > 0 ? conversions / visitors : 0;
|
|
316
|
-
|
|
317
|
-
if (variant === 'control') {
|
|
318
|
-
controlVisitors = visitors;
|
|
319
|
-
controlConversions = conversions;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
variants.push({
|
|
323
|
-
variant,
|
|
324
|
-
visitors,
|
|
325
|
-
conversions,
|
|
326
|
-
conversionRate,
|
|
327
|
-
isSignificant: false,
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Calculate lift and significance for non-control variants
|
|
332
|
-
const controlRate = controlVisitors > 0 ? controlConversions / controlVisitors : 0;
|
|
333
|
-
for (const result of variants) {
|
|
334
|
-
if (result.variant !== 'control' && controlVisitors > 0) {
|
|
335
|
-
result.lift = controlRate > 0
|
|
336
|
-
? ((result.conversionRate - controlRate) / controlRate) * 100
|
|
337
|
-
: 0;
|
|
338
|
-
result.pValue = zTest(
|
|
339
|
-
controlConversions, controlVisitors,
|
|
340
|
-
result.conversions, result.visitors
|
|
341
|
-
);
|
|
342
|
-
result.isSignificant = result.pValue < 0.05;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Sort: control first, then by variant name
|
|
347
|
-
variants.sort((a, b) => {
|
|
348
|
-
if (a.variant === 'control') return -1;
|
|
349
|
-
if (b.variant === 'control') return 1;
|
|
350
|
-
return a.variant.localeCompare(b.variant);
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
return Response.json({
|
|
354
|
-
experimentId,
|
|
355
|
-
variants,
|
|
356
|
-
}, {
|
|
357
|
-
headers: {
|
|
358
|
-
'Access-Control-Allow-Origin': '*',
|
|
359
|
-
'Cache-Control': 'no-cache',
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
} catch (error) {
|
|
363
|
-
return Response.json({ error: 'Failed to query results' }, { status: 500 });
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
`;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// lib/server/ab/trackingScript.ts
|
|
370
|
-
function generateTrackingScript(experimentId, goals) {
|
|
371
|
-
const goalsJSON = JSON.stringify(goals);
|
|
372
|
-
return `(function(){
|
|
373
|
-
var EXP_ID=${JSON.stringify(experimentId)};
|
|
374
|
-
var GOALS=${goalsJSON};
|
|
375
|
-
|
|
376
|
-
function getCookie(n){var m=document.cookie.match(new RegExp('(?:^|;\\\\s*)'+n+'=([^;]*)'));return m?decodeURIComponent(m[1]):null}
|
|
377
|
-
function setCookie(n,v,d){var e=new Date();e.setTime(e.getTime()+d*864e5);document.cookie=n+'='+encodeURIComponent(v)+';path=/;expires='+e.toUTCString()+';SameSite=Lax'}
|
|
378
|
-
|
|
379
|
-
var variant=getCookie('meno_variant')||'control';
|
|
380
|
-
var visitor=getCookie('meno_visitor');
|
|
381
|
-
if(!visitor){visitor=Math.random().toString(36).slice(2)+Date.now().toString(36);setCookie('meno_visitor',visitor,365)}
|
|
382
|
-
|
|
383
|
-
function track(type,goalId){
|
|
384
|
-
try{navigator.sendBeacon('/api/ab-track',JSON.stringify({experimentId:EXP_ID,visitorId:visitor,variant:variant,eventType:type,goalId:goalId||null,url:location.pathname}))}catch(e){}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
track('pageview');
|
|
388
|
-
|
|
389
|
-
GOALS.forEach(function(g){
|
|
390
|
-
if(g.type==='click'&&g.selector){
|
|
391
|
-
document.addEventListener('click',function(e){
|
|
392
|
-
if(e.target&&e.target.closest&&e.target.closest(g.selector)){track('conversion',g.id)}
|
|
393
|
-
})
|
|
394
|
-
}
|
|
395
|
-
if(g.type==='navigation'&&g.url){
|
|
396
|
-
if(location.pathname===g.url||location.href.indexOf(g.url)>-1){track('conversion',g.id)}
|
|
397
|
-
}
|
|
398
|
-
if(g.type==='custom'&&g.event){
|
|
399
|
-
window.addEventListener(g.event,function(){track('conversion',g.id)})
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
})();`;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// build-static.ts
|
|
406
|
-
var buildErrors = [];
|
|
407
|
-
function hashContent(content) {
|
|
408
|
-
return createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
409
|
-
}
|
|
410
|
-
function formatBunLog(log) {
|
|
411
|
-
const parts = [];
|
|
412
|
-
if (log.position) {
|
|
413
|
-
const pos = log.position;
|
|
414
|
-
if (pos.file) parts.push(`File: ${pos.file}`);
|
|
415
|
-
if (pos.line !== void 0) parts.push(`Line ${pos.line}:${pos.column || 0}`);
|
|
416
|
-
if (pos.lineText) parts.push(` ${pos.lineText}`);
|
|
417
|
-
}
|
|
418
|
-
if (log.message) {
|
|
419
|
-
parts.push(log.message);
|
|
420
|
-
} else if (log.text) {
|
|
421
|
-
parts.push(log.text);
|
|
422
|
-
}
|
|
423
|
-
if (parts.length === 0) {
|
|
424
|
-
try {
|
|
425
|
-
return JSON.stringify(log, null, 2);
|
|
426
|
-
} catch {
|
|
427
|
-
return String(log);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return parts.join("\n");
|
|
431
|
-
}
|
|
432
|
-
async function minifyJS2(code) {
|
|
433
|
-
const result = await minifyJS(code);
|
|
434
|
-
if (result.success) {
|
|
435
|
-
return result.code;
|
|
436
|
-
}
|
|
437
|
-
throw new Error(`JavaScript minification failed:
|
|
438
|
-
${result.errors.join("\n\n")}`);
|
|
439
|
-
}
|
|
440
|
-
var jsFileCache = /* @__PURE__ */ new Map();
|
|
441
|
-
async function getScriptPath(jsContent, distDir) {
|
|
442
|
-
const minified = await minifyJS2(jsContent);
|
|
443
|
-
const hash = hashContent(minified);
|
|
444
|
-
if (jsFileCache.has(hash)) {
|
|
445
|
-
return jsFileCache.get(hash);
|
|
446
|
-
}
|
|
447
|
-
const scriptsDir = join(distDir, "_scripts");
|
|
448
|
-
if (!existsSync(scriptsDir)) {
|
|
449
|
-
mkdirSync(scriptsDir, { recursive: true });
|
|
450
|
-
}
|
|
451
|
-
const scriptPath = `/_scripts/${hash}.js`;
|
|
452
|
-
const fullPath = join(distDir, "_scripts", `${hash}.js`);
|
|
453
|
-
await writeFile(fullPath, minified, "utf-8");
|
|
454
|
-
jsFileCache.set(hash, scriptPath);
|
|
455
|
-
return scriptPath;
|
|
456
|
-
}
|
|
457
|
-
function copyDirectory(src, dest) {
|
|
458
|
-
if (!existsSync(src)) {
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
if (!existsSync(dest)) {
|
|
462
|
-
mkdirSync(dest, { recursive: true });
|
|
463
|
-
}
|
|
464
|
-
const files = readdirSync(src);
|
|
465
|
-
for (const file of files) {
|
|
466
|
-
const srcPath = join(src, file);
|
|
467
|
-
const destPath = join(dest, file);
|
|
468
|
-
const stat = statSync(srcPath);
|
|
469
|
-
if (stat.isDirectory()) {
|
|
470
|
-
copyDirectory(srcPath, destPath);
|
|
471
|
-
} else {
|
|
472
|
-
copyFileSync(srcPath, destPath);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
function getLocalizedOutputPath(basePath, locale, defaultLocale, distDir, slugs) {
|
|
477
|
-
let slug;
|
|
478
|
-
if (slugs && slugs[locale]) {
|
|
479
|
-
slug = slugs[locale];
|
|
480
|
-
} else if (basePath === "/") {
|
|
481
|
-
slug = "";
|
|
482
|
-
} else {
|
|
483
|
-
slug = basePath.substring(1);
|
|
484
|
-
}
|
|
485
|
-
const fileName = slug === "" ? "index.html" : `${slug}.html`;
|
|
486
|
-
if (locale === defaultLocale) {
|
|
487
|
-
return `${distDir}/${fileName}`;
|
|
488
|
-
}
|
|
489
|
-
return `${distDir}/${locale}/${fileName}`;
|
|
490
|
-
}
|
|
491
|
-
function getDisplayPath(basePath, locale, defaultLocale, slugs) {
|
|
492
|
-
let slug;
|
|
493
|
-
if (slugs && slugs[locale]) {
|
|
494
|
-
slug = slugs[locale];
|
|
495
|
-
} else if (basePath === "/") {
|
|
496
|
-
slug = "";
|
|
497
|
-
} else {
|
|
498
|
-
slug = basePath.substring(1);
|
|
499
|
-
}
|
|
500
|
-
if (locale === defaultLocale) {
|
|
501
|
-
return slug === "" ? "/" : `/${slug}`;
|
|
502
|
-
}
|
|
503
|
-
return slug === "" ? `/${locale}` : `/${locale}/${slug}`;
|
|
504
|
-
}
|
|
505
|
-
async function generateRobotsTxt(siteUrl, distDir) {
|
|
506
|
-
const content = `User-agent: *
|
|
507
|
-
Allow: /
|
|
508
|
-
|
|
509
|
-
Sitemap: ${siteUrl}/sitemap.xml
|
|
510
|
-
`;
|
|
511
|
-
await writeFile(join(distDir, "robots.txt"), content, "utf-8");
|
|
512
|
-
}
|
|
513
|
-
async function generateSitemap(urls, siteUrl, distDir) {
|
|
514
|
-
const sortedUrls = [...urls].sort();
|
|
515
|
-
const urlEntries = sortedUrls.map((url) => ` <url><loc>${siteUrl}${url}</loc></url>`).join("\n");
|
|
516
|
-
const content = `<?xml version="1.0" encoding="UTF-8"?>
|
|
517
|
-
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
518
|
-
${urlEntries}
|
|
519
|
-
</urlset>
|
|
520
|
-
`;
|
|
521
|
-
await writeFile(join(distDir, "sitemap.xml"), content, "utf-8");
|
|
522
|
-
}
|
|
523
|
-
function cleanDist(distDir = projectPaths.dist()) {
|
|
524
|
-
if (!existsSync(distDir)) {
|
|
525
|
-
mkdirSync(distDir, { recursive: true });
|
|
526
|
-
return;
|
|
527
|
-
}
|
|
528
|
-
const files = readdirSync(distDir);
|
|
529
|
-
let cleaned = 0;
|
|
530
|
-
for (const file of files) {
|
|
531
|
-
if (file === "fonts" || file === "images" || file === "icons" || file === "assets" || file === "videos") {
|
|
532
|
-
continue;
|
|
533
|
-
}
|
|
534
|
-
try {
|
|
535
|
-
const filePath = join(distDir, file);
|
|
536
|
-
const stat = statSync(filePath);
|
|
537
|
-
if (stat.isDirectory()) {
|
|
538
|
-
rmSync(filePath, { recursive: true, force: true });
|
|
539
|
-
} else {
|
|
540
|
-
rmSync(filePath, { force: true });
|
|
541
|
-
}
|
|
542
|
-
cleaned++;
|
|
543
|
-
} catch (error) {
|
|
544
|
-
console.warn(`\u26A0\uFE0F Could not remove ${file}:`, error);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
if (cleaned > 0) {
|
|
548
|
-
console.log(`\u{1F9F9} Cleaned ${cleaned} file(s) from dist
|
|
549
|
-
`);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
function isCMSPage(pageData) {
|
|
553
|
-
return pageData.meta?.source === "cms" && !!pageData.meta?.cms;
|
|
554
|
-
}
|
|
555
|
-
function buildCMSItemPath(urlPattern, item, slugField, locale, i18nConfig) {
|
|
556
|
-
let slug = item[slugField] ?? item._slug ?? item._id;
|
|
557
|
-
if (isI18nValue(slug)) {
|
|
558
|
-
slug = resolveI18nValue(slug, locale, i18nConfig);
|
|
559
|
-
}
|
|
560
|
-
return urlPattern.replace("{{slug}}", String(slug));
|
|
561
|
-
}
|
|
562
|
-
async function generateStaticDataFiles(staticCollections, distDir) {
|
|
563
|
-
if (staticCollections.size === 0) return;
|
|
564
|
-
console.log(`
|
|
565
|
-
\u{1F4E6} Generating static data files...`);
|
|
566
|
-
for (const [collectionId, data] of staticCollections) {
|
|
567
|
-
const dataDir = join(distDir, "data", collectionId);
|
|
568
|
-
if (!existsSync(dataDir)) {
|
|
569
|
-
mkdirSync(dataDir, { recursive: true });
|
|
570
|
-
}
|
|
571
|
-
const jsonPath = join(dataDir, "index.json");
|
|
572
|
-
await writeFile(jsonPath, JSON.stringify(data.items), "utf-8");
|
|
573
|
-
console.log(` \u2705 /data/${collectionId}/index.json (${data.items.length} items)`);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
async function buildCMSTemplates(templatesDir, globalComponents, i18nConfig, slugMappings, distDir, cmsService, generatedUrls, staticCollections, siteUrl, abTrackingScript) {
|
|
577
|
-
let successCount = 0;
|
|
578
|
-
let errorCount = 0;
|
|
579
|
-
if (!existsSync(templatesDir)) {
|
|
580
|
-
return { success: 0, errors: 0 };
|
|
581
|
-
}
|
|
582
|
-
const templateFiles = readdirSync(templatesDir).filter((f) => f.endsWith(".json"));
|
|
583
|
-
if (templateFiles.length === 0) {
|
|
584
|
-
return { success: 0, errors: 0 };
|
|
585
|
-
}
|
|
586
|
-
console.log(`
|
|
587
|
-
\u{1F4DD} Processing ${templateFiles.length} CMS template(s)...
|
|
588
|
-
`);
|
|
589
|
-
for (const file of templateFiles) {
|
|
590
|
-
const templateContent = await loadJSONFile(join(templatesDir, file));
|
|
591
|
-
if (!templateContent) continue;
|
|
592
|
-
try {
|
|
593
|
-
const pageData = parseJSON(templateContent);
|
|
594
|
-
const isDevBuild = process.env.MENO_DEV_BUILD === "true";
|
|
595
|
-
if (pageData.meta?.draft === true && !isDevBuild) {
|
|
596
|
-
console.log(`\u23ED\uFE0F Skipping draft template: ${file}`);
|
|
597
|
-
continue;
|
|
598
|
-
}
|
|
599
|
-
if (!isCMSPage(pageData)) {
|
|
600
|
-
console.warn(`\u26A0\uFE0F ${file} is in templates/ but missing meta.source: "cms"`);
|
|
601
|
-
continue;
|
|
602
|
-
}
|
|
603
|
-
const cmsSchema = pageData.meta.cms;
|
|
604
|
-
console.log(`\u{1F4DD} CMS Collection: ${cmsSchema.id}`);
|
|
605
|
-
const items = await cmsService.queryItems({ collection: cmsSchema.id });
|
|
606
|
-
if (items.length === 0) {
|
|
607
|
-
console.log(` \u26A0\uFE0F No items found in cms/${cmsSchema.id}/`);
|
|
608
|
-
continue;
|
|
609
|
-
}
|
|
610
|
-
console.log(` Found ${items.length} item(s)`);
|
|
611
|
-
let clientDataCollections;
|
|
612
|
-
if (cmsSchema.clientData?.enabled) {
|
|
613
|
-
const publishedItems = items.filter((item) => isItemFullyPublished(item));
|
|
614
|
-
const clientData = prepareClientData(cmsSchema.id, publishedItems, cmsSchema.clientData);
|
|
615
|
-
if (clientData) {
|
|
616
|
-
if (clientData.strategy === "inline") {
|
|
617
|
-
clientDataCollections = /* @__PURE__ */ new Map([[cmsSchema.id, clientData]]);
|
|
618
|
-
console.log(` \u{1F4E6} Client data (inline): ${clientData.items.length} items (${clientData.config.fields?.length || "all"} fields)`);
|
|
619
|
-
} else if (clientData.strategy === "static") {
|
|
620
|
-
staticCollections.set(cmsSchema.id, clientData);
|
|
621
|
-
console.log(` \u{1F4E6} Client data (static): ${clientData.items.length} items \u2192 /data/${cmsSchema.id}/index.json`);
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
for (const item of items) {
|
|
626
|
-
for (const localeConfig of i18nConfig.locales) {
|
|
627
|
-
const locale = localeConfig.code;
|
|
628
|
-
const isDevBuild2 = process.env.MENO_DEV_BUILD === "true";
|
|
629
|
-
if (!isDevBuild2 && isItemDraftForLocale(item, locale)) {
|
|
630
|
-
console.log(` \u23ED\uFE0F Skipping draft: ${item._filename || item._id} [${locale}]`);
|
|
631
|
-
continue;
|
|
632
|
-
}
|
|
633
|
-
const baseUrl = siteUrl || "";
|
|
634
|
-
const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);
|
|
635
|
-
const itemWithUrl = { ...item, _url: itemPath };
|
|
636
|
-
const result = await generateSSRHTML({
|
|
637
|
-
pageData,
|
|
638
|
-
globalComponents,
|
|
639
|
-
pagePath: itemPath,
|
|
640
|
-
baseUrl,
|
|
641
|
-
useBuiltBundle: true,
|
|
642
|
-
locale,
|
|
643
|
-
slugMappings,
|
|
644
|
-
cmsContext: { cms: itemWithUrl },
|
|
645
|
-
cmsService,
|
|
646
|
-
returnSeparateJS: true,
|
|
647
|
-
pageLibraries: pageData.meta?.libraries,
|
|
648
|
-
pageCustomCode: pageData.meta?.customCode,
|
|
649
|
-
clientDataCollections,
|
|
650
|
-
isProductionBuild: true
|
|
651
|
-
});
|
|
652
|
-
let finalHtml = result.html;
|
|
653
|
-
if (result.javascript) {
|
|
654
|
-
const scriptPath = await getScriptPath(result.javascript, distDir);
|
|
655
|
-
finalHtml = finalHtml.replace("</body>", ` <script src="${scriptPath}" defer></script>
|
|
656
|
-
</body>`);
|
|
657
|
-
}
|
|
658
|
-
if (abTrackingScript) {
|
|
659
|
-
finalHtml = injectTrackingScript(finalHtml, abTrackingScript);
|
|
660
|
-
}
|
|
661
|
-
const outputPath = locale === i18nConfig.defaultLocale ? `${distDir}${itemPath}.html` : `${distDir}/${locale}${itemPath}.html`;
|
|
662
|
-
const outputDir = outputPath.substring(0, outputPath.lastIndexOf("/"));
|
|
663
|
-
if (outputDir && !existsSync(outputDir)) {
|
|
664
|
-
mkdirSync(outputDir, { recursive: true });
|
|
665
|
-
}
|
|
666
|
-
await writeFile(outputPath, finalHtml, "utf-8");
|
|
667
|
-
const displayPath = locale === i18nConfig.defaultLocale ? itemPath : `/${locale}${itemPath}`;
|
|
668
|
-
generatedUrls.add(displayPath);
|
|
669
|
-
console.log(` \u2705 ${displayPath}`);
|
|
670
|
-
successCount++;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
} catch (error) {
|
|
674
|
-
let errorMessage;
|
|
675
|
-
if (error instanceof Error) {
|
|
676
|
-
if ("errors" in error && Array.isArray(error.errors)) {
|
|
677
|
-
errorMessage = error.errors.map((e) => e.stack || e.message || String(e)).join("\n\n");
|
|
678
|
-
} else if (error.cause) {
|
|
679
|
-
const causeMsg = error.cause instanceof Error ? error.cause.stack || error.cause.message : String(error.cause);
|
|
680
|
-
errorMessage = `${error.stack || error.message}
|
|
681
|
-
|
|
682
|
-
Caused by:
|
|
683
|
-
${causeMsg}`;
|
|
684
|
-
} else if ("logs" in error && Array.isArray(error.logs)) {
|
|
685
|
-
errorMessage = error.logs.map(formatBunLog).join("\n\n");
|
|
686
|
-
} else {
|
|
687
|
-
errorMessage = error.stack || error.message;
|
|
688
|
-
}
|
|
689
|
-
} else if (typeof error === "object" && error !== null) {
|
|
690
|
-
if (error.logs && Array.isArray(error.logs)) {
|
|
691
|
-
errorMessage = error.logs.map(formatBunLog).join("\n\n");
|
|
692
|
-
} else {
|
|
693
|
-
errorMessage = String(error);
|
|
694
|
-
}
|
|
695
|
-
} else {
|
|
696
|
-
errorMessage = String(error);
|
|
697
|
-
}
|
|
698
|
-
if (errorMessage === "Bundle failed" || errorMessage.includes("Bundle failed\n")) {
|
|
699
|
-
try {
|
|
700
|
-
const inspected = inspect(error);
|
|
701
|
-
if (inspected && inspected !== "[object Object]" && inspected.length > errorMessage.length) {
|
|
702
|
-
errorMessage = inspected;
|
|
703
|
-
}
|
|
704
|
-
} catch {
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
console.error(`\u274C Error processing ${file}:`, error);
|
|
708
|
-
buildErrors.push({
|
|
709
|
-
file: `templates/${file}`,
|
|
710
|
-
message: errorMessage,
|
|
711
|
-
type: errorMessage.includes("minification") || errorMessage.includes("minify") ? "minify" : "cms"
|
|
712
|
-
});
|
|
713
|
-
errorCount++;
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
return { success: successCount, errors: errorCount };
|
|
717
|
-
}
|
|
718
|
-
async function loadRunningExperiments() {
|
|
719
|
-
const experimentsPath = join(projectPaths.project, "experiments.json");
|
|
720
|
-
if (!existsSync(experimentsPath)) return [];
|
|
721
|
-
try {
|
|
722
|
-
const content = await readFile(experimentsPath, "utf-8");
|
|
723
|
-
const data = JSON.parse(content);
|
|
724
|
-
const experiments = data.experiments || [];
|
|
725
|
-
return experiments.filter((e) => e.status === "running");
|
|
726
|
-
} catch {
|
|
727
|
-
return [];
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
function injectTrackingScript(html, trackingJs) {
|
|
731
|
-
const scriptTag = `<script>${trackingJs}</script>`;
|
|
732
|
-
return html.replace("</head>", `${scriptTag}
|
|
733
|
-
</head>`);
|
|
734
|
-
}
|
|
735
|
-
async function generateABFunctions(experiments, distDir) {
|
|
736
|
-
const middlewareContent = generateMiddleware(experiments);
|
|
737
|
-
if (middlewareContent) {
|
|
738
|
-
const middlewarePath = join(distDir, "functions", "_middleware.ts");
|
|
739
|
-
const middlewareDir = join(distDir, "functions");
|
|
740
|
-
if (!existsSync(middlewareDir)) {
|
|
741
|
-
mkdirSync(middlewareDir, { recursive: true });
|
|
742
|
-
}
|
|
743
|
-
await writeFile(middlewarePath, middlewareContent, "utf-8");
|
|
744
|
-
}
|
|
745
|
-
const trackContent = generateTrackFunction();
|
|
746
|
-
const trackDir = join(distDir, "functions", "api");
|
|
747
|
-
if (!existsSync(trackDir)) {
|
|
748
|
-
mkdirSync(trackDir, { recursive: true });
|
|
749
|
-
}
|
|
750
|
-
await writeFile(join(trackDir, "ab-track.ts"), trackContent, "utf-8");
|
|
751
|
-
const resultsContent = generateResultsFunction();
|
|
752
|
-
await writeFile(join(trackDir, "ab-results.ts"), resultsContent, "utf-8");
|
|
753
|
-
}
|
|
754
|
-
async function buildStaticPages(outDir) {
|
|
755
|
-
console.log("\u{1F3D7}\uFE0F Building static HTML files...\n");
|
|
756
|
-
buildErrors.length = 0;
|
|
757
|
-
clearJSValidationCache();
|
|
758
|
-
const { configService } = await import("./configService-R3OGU2UD.js");
|
|
759
|
-
configService.reset();
|
|
760
|
-
const projectConfig = await loadProjectConfig();
|
|
761
|
-
const siteUrl = projectConfig.siteUrl?.replace(/\/$/, "");
|
|
762
|
-
const generatedUrls = /* @__PURE__ */ new Set();
|
|
763
|
-
const runningExperiments = await loadRunningExperiments();
|
|
764
|
-
let trackingScript = null;
|
|
765
|
-
if (runningExperiments.length > 0) {
|
|
766
|
-
const exp = runningExperiments[0];
|
|
767
|
-
trackingScript = generateTrackingScript(exp.id, exp.conversionGoals);
|
|
768
|
-
console.log(`\u{1F9EA} A/B experiment active: "${exp.name}" (${exp.variants.length} variant(s))
|
|
769
|
-
`);
|
|
770
|
-
}
|
|
771
|
-
const i18nConfig = await loadI18nConfig();
|
|
772
|
-
console.log(`\u{1F310} Locales: ${i18nConfig.locales.map((l) => l.code).join(", ")} (default: ${i18nConfig.defaultLocale})
|
|
773
|
-
`);
|
|
774
|
-
await migrateTemplatesDirectory();
|
|
775
|
-
const distDir = outDir || projectPaths.dist();
|
|
776
|
-
cleanDist(distDir);
|
|
777
|
-
jsFileCache.clear();
|
|
778
|
-
console.log("\u{1F4E6} Copying assets...");
|
|
779
|
-
const errorsPath = join(distDir, "_errors.json");
|
|
780
|
-
if (existsSync(errorsPath)) {
|
|
781
|
-
unlinkSync(errorsPath);
|
|
782
|
-
}
|
|
783
|
-
copyDirectory(projectPaths.fonts(), join(distDir, "fonts"));
|
|
784
|
-
copyDirectory(projectPaths.images(), join(distDir, "images"));
|
|
785
|
-
copyDirectory(projectPaths.icons(), join(distDir, "icons"));
|
|
786
|
-
copyDirectory(projectPaths.assets(), join(distDir, "assets"));
|
|
787
|
-
copyDirectory(projectPaths.videos(), join(distDir, "videos"));
|
|
788
|
-
const librariesDir = join(projectPaths.project, "libraries");
|
|
789
|
-
if (existsSync(librariesDir)) {
|
|
790
|
-
copyDirectory(librariesDir, join(distDir, "libraries"));
|
|
791
|
-
}
|
|
792
|
-
const functionsDir = projectPaths.functions();
|
|
793
|
-
if (existsSync(functionsDir)) {
|
|
794
|
-
copyDirectory(functionsDir, join(distDir, "functions"));
|
|
795
|
-
}
|
|
796
|
-
const hostingFiles = [];
|
|
797
|
-
const rootFilesToCopy = [
|
|
798
|
-
"_headers",
|
|
799
|
-
// Netlify/Cloudflare headers
|
|
800
|
-
"_redirects",
|
|
801
|
-
// Netlify/Cloudflare redirects
|
|
802
|
-
"llms.txt",
|
|
803
|
-
// LLM context
|
|
804
|
-
"humans.txt",
|
|
805
|
-
// Team credits
|
|
806
|
-
"ads.txt",
|
|
807
|
-
// Ad verification
|
|
808
|
-
"security.txt",
|
|
809
|
-
// Security contact
|
|
810
|
-
"CNAME",
|
|
811
|
-
// GitHub Pages domain
|
|
812
|
-
"manifest.json",
|
|
813
|
-
// PWA manifest
|
|
814
|
-
"site.webmanifest"
|
|
815
|
-
// PWA manifest (alt)
|
|
816
|
-
];
|
|
817
|
-
for (const file of rootFilesToCopy) {
|
|
818
|
-
const filePath = join(projectPaths.project, file);
|
|
819
|
-
if (existsSync(filePath)) {
|
|
820
|
-
copyFileSync(filePath, join(distDir, file));
|
|
821
|
-
hostingFiles.push(file);
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
const wellKnownDir = join(projectPaths.project, ".well-known");
|
|
825
|
-
if (existsSync(wellKnownDir)) {
|
|
826
|
-
copyDirectory(wellKnownDir, join(distDir, ".well-known"));
|
|
827
|
-
hostingFiles.push(".well-known/");
|
|
828
|
-
}
|
|
829
|
-
const parts = ["Assets"];
|
|
830
|
-
if (existsSync(functionsDir)) parts.push("functions");
|
|
831
|
-
if (hostingFiles.length > 0) parts.push(hostingFiles.join(", "));
|
|
832
|
-
console.log(`\u2705 ${parts.join(", ")} copied
|
|
833
|
-
`);
|
|
834
|
-
const { components, warnings, errors } = await loadComponentDirectory(projectPaths.components());
|
|
835
|
-
const globalComponents = {};
|
|
836
|
-
components.forEach((value, key) => {
|
|
837
|
-
globalComponents[key] = value;
|
|
838
|
-
});
|
|
839
|
-
for (const warning of warnings) console.warn(`\u26A0\uFE0F ${warning}`);
|
|
840
|
-
for (const error of errors) console.error(`\u274C ${error}`);
|
|
841
|
-
console.log(`\u2705 Loaded ${components.size} global component(s)
|
|
842
|
-
`);
|
|
843
|
-
const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());
|
|
844
|
-
const cmsService = new CMSService(cmsProvider);
|
|
845
|
-
await cmsService.initialize();
|
|
846
|
-
console.log(`\u2705 CMS service initialized
|
|
847
|
-
`);
|
|
848
|
-
const pagesDir = projectPaths.pages();
|
|
849
|
-
if (!existsSync(pagesDir)) {
|
|
850
|
-
console.error("\u274C Pages directory not found!");
|
|
851
|
-
process.exit(1);
|
|
852
|
-
}
|
|
853
|
-
const pageFiles = [];
|
|
854
|
-
function scanPagesDir(dir, prefix) {
|
|
855
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
856
|
-
for (const entry of entries) {
|
|
857
|
-
if (entry.isFile() && entry.name.endsWith(".json")) {
|
|
858
|
-
pageFiles.push(prefix ? `${prefix}/${entry.name}` : entry.name);
|
|
859
|
-
} else if (entry.isDirectory()) {
|
|
860
|
-
scanPagesDir(join(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
scanPagesDir(pagesDir, "");
|
|
865
|
-
if (pageFiles.length === 0) {
|
|
866
|
-
console.warn("\u26A0\uFE0F No pages found in ./pages directory");
|
|
867
|
-
return;
|
|
868
|
-
}
|
|
869
|
-
console.log(`\u{1F4C4} Found ${pageFiles.length} page(s) to build
|
|
870
|
-
`);
|
|
871
|
-
const slugMappings = [];
|
|
872
|
-
const allPageLibraries = [];
|
|
873
|
-
for (const file of pageFiles) {
|
|
874
|
-
const pageName = file.replace(".json", "");
|
|
875
|
-
const basePath = mapPageNameToPath(pageName);
|
|
876
|
-
const pageContent = await loadJSONFile(join(pagesDir, file));
|
|
877
|
-
if (pageContent) {
|
|
878
|
-
try {
|
|
879
|
-
const pageData = parseJSON(pageContent);
|
|
880
|
-
if (pageData.meta?.slugs) {
|
|
881
|
-
const pageId = basePath === "/" ? "index" : basePath.substring(1);
|
|
882
|
-
slugMappings.push({ pageId, slugs: pageData.meta.slugs });
|
|
883
|
-
}
|
|
884
|
-
if (pageData.meta?.libraries) {
|
|
885
|
-
allPageLibraries.push(pageData.meta.libraries);
|
|
886
|
-
}
|
|
887
|
-
} catch {
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
{
|
|
892
|
-
await configService.load();
|
|
893
|
-
const cspConfig = configService.getCSP();
|
|
894
|
-
if (cspConfig && Object.keys(cspConfig).length > 0) {
|
|
895
|
-
const globalLibraries = configService.getLibraries();
|
|
896
|
-
const componentLibraries = collectComponentLibraries(globalComponents);
|
|
897
|
-
const allJs = [
|
|
898
|
-
...globalLibraries.js || [],
|
|
899
|
-
...componentLibraries.js || [],
|
|
900
|
-
...allPageLibraries.flatMap((p) => p.js || [])
|
|
901
|
-
];
|
|
902
|
-
const allCss = [
|
|
903
|
-
...globalLibraries.css || [],
|
|
904
|
-
...componentLibraries.css || [],
|
|
905
|
-
...allPageLibraries.flatMap((p) => p.css || [])
|
|
906
|
-
];
|
|
907
|
-
const allLibs = { js: allJs, css: allCss };
|
|
908
|
-
const buildLibs = filterLibrariesByContext(allLibs, "build");
|
|
909
|
-
const { scriptOrigins, styleOrigins } = extractLibraryOrigins(buildLibs);
|
|
910
|
-
const extraScripts = [
|
|
911
|
-
...cspConfig.scriptSrc || [],
|
|
912
|
-
...Array.from(scriptOrigins)
|
|
913
|
-
].join(" ");
|
|
914
|
-
const extraStyles = [
|
|
915
|
-
...cspConfig.styleSrc || [],
|
|
916
|
-
...Array.from(styleOrigins)
|
|
917
|
-
].join(" ");
|
|
918
|
-
const extraConnect = cspConfig.connectSrc?.join(" ") || "";
|
|
919
|
-
const extraFrames = cspConfig.frameSrc?.join(" ") || "";
|
|
920
|
-
const extraFonts = cspConfig.fontSrc?.join(" ") || "";
|
|
921
|
-
const extraImgs = cspConfig.imgSrc?.join(" ") || "";
|
|
922
|
-
const cspDirectives = [
|
|
923
|
-
"default-src 'self'",
|
|
924
|
-
`script-src 'self' https://f.vimeocdn.com https://player.vimeo.com https://www.youtube.com https://s.ytimg.com ${extraScripts}`.trim(),
|
|
925
|
-
`style-src 'self' 'unsafe-inline' https://f.vimeocdn.com ${extraStyles}`.trim(),
|
|
926
|
-
`img-src 'self' data: https: ${extraImgs}`.trim(),
|
|
927
|
-
`connect-src 'self' https://vimeo.com https://*.vimeocdn.com ${extraConnect}`.trim(),
|
|
928
|
-
`frame-src https://player.vimeo.com https://vimeo.com https://www.youtube.com https://www.youtube-nocookie.com ${extraFrames}`.trim(),
|
|
929
|
-
`font-src 'self' data: ${extraFonts}`.trim(),
|
|
930
|
-
"media-src 'self' https: blob:"
|
|
931
|
-
].join("; ");
|
|
932
|
-
const headersContent = `/*
|
|
933
|
-
Content-Security-Policy: ${cspDirectives}
|
|
934
|
-
`;
|
|
935
|
-
writeFileSync(join(distDir, "_headers"), headersContent);
|
|
936
|
-
console.log(`\u2705 Generated _headers with CSP (auto-included ${scriptOrigins.size + styleOrigins.size} library origin(s))
|
|
937
|
-
`);
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
let successCount = 0;
|
|
941
|
-
let errorCount = 0;
|
|
942
|
-
for (const file of pageFiles) {
|
|
943
|
-
const pageName = file.replace(".json", "");
|
|
944
|
-
const basePath = mapPageNameToPath(pageName);
|
|
945
|
-
const pageContent = await loadJSONFile(join(pagesDir, file));
|
|
946
|
-
if (!pageContent) {
|
|
947
|
-
console.warn(`\u26A0\uFE0F Skipping ${basePath} (empty file)`);
|
|
948
|
-
errorCount++;
|
|
949
|
-
continue;
|
|
950
|
-
}
|
|
951
|
-
try {
|
|
952
|
-
const pageData = parseJSON(pageContent);
|
|
953
|
-
const isDevBuild = process.env.MENO_DEV_BUILD === "true";
|
|
954
|
-
if (pageData.meta?.draft === true && !isDevBuild) {
|
|
955
|
-
console.log(`\u23ED\uFE0F Skipping draft: ${basePath}`);
|
|
956
|
-
continue;
|
|
957
|
-
}
|
|
958
|
-
const slugs = pageData.meta?.slugs;
|
|
959
|
-
for (const localeConfig of i18nConfig.locales) {
|
|
960
|
-
const locale = localeConfig.code;
|
|
961
|
-
const baseUrl = siteUrl || "";
|
|
962
|
-
const urlPath = getDisplayPath(basePath, locale, i18nConfig.defaultLocale, slugs);
|
|
963
|
-
const result = await generateSSRHTML({
|
|
964
|
-
pageData,
|
|
965
|
-
globalComponents,
|
|
966
|
-
pagePath: urlPath,
|
|
967
|
-
baseUrl,
|
|
968
|
-
useBuiltBundle: true,
|
|
969
|
-
locale,
|
|
970
|
-
slugMappings,
|
|
971
|
-
cmsService,
|
|
972
|
-
returnSeparateJS: true,
|
|
973
|
-
pageLibraries: pageData.meta?.libraries,
|
|
974
|
-
pageCustomCode: pageData.meta?.customCode,
|
|
975
|
-
isProductionBuild: true
|
|
976
|
-
});
|
|
977
|
-
let finalHtml = result.html;
|
|
978
|
-
if (result.javascript) {
|
|
979
|
-
const scriptPath = await getScriptPath(result.javascript, distDir);
|
|
980
|
-
finalHtml = finalHtml.replace("</body>", ` <script src="${scriptPath}" defer></script>
|
|
981
|
-
</body>`);
|
|
982
|
-
}
|
|
983
|
-
if (trackingScript) {
|
|
984
|
-
finalHtml = injectTrackingScript(finalHtml, trackingScript);
|
|
985
|
-
}
|
|
986
|
-
const outputPath = getLocalizedOutputPath(basePath, locale, i18nConfig.defaultLocale, distDir, slugs);
|
|
987
|
-
const outputDir = outputPath.substring(0, outputPath.lastIndexOf("/"));
|
|
988
|
-
if (outputDir && !existsSync(outputDir)) {
|
|
989
|
-
mkdirSync(outputDir, { recursive: true });
|
|
990
|
-
}
|
|
991
|
-
if (urlPath === "/") {
|
|
992
|
-
console.log("[DEBUG] Last 500 chars of HTML:", finalHtml.slice(-500));
|
|
993
|
-
}
|
|
994
|
-
await writeFile(outputPath, finalHtml, "utf-8");
|
|
995
|
-
generatedUrls.add(urlPath);
|
|
996
|
-
console.log(`\u2705 Built: ${urlPath} \u2192 ${outputPath}`);
|
|
997
|
-
successCount++;
|
|
998
|
-
}
|
|
999
|
-
} catch (error) {
|
|
1000
|
-
let errorMessage;
|
|
1001
|
-
if (error instanceof Error) {
|
|
1002
|
-
if ("errors" in error && Array.isArray(error.errors)) {
|
|
1003
|
-
errorMessage = error.errors.map((e) => e.stack || e.message || String(e)).join("\n\n");
|
|
1004
|
-
} else if (error.cause) {
|
|
1005
|
-
const causeMsg = error.cause instanceof Error ? error.cause.stack || error.cause.message : String(error.cause);
|
|
1006
|
-
errorMessage = `${error.stack || error.message}
|
|
1007
|
-
|
|
1008
|
-
Caused by:
|
|
1009
|
-
${causeMsg}`;
|
|
1010
|
-
} else if ("logs" in error && Array.isArray(error.logs)) {
|
|
1011
|
-
errorMessage = error.logs.map(formatBunLog).join("\n\n");
|
|
1012
|
-
} else {
|
|
1013
|
-
errorMessage = error.stack || error.message;
|
|
1014
|
-
}
|
|
1015
|
-
} else if (typeof error === "object" && error !== null) {
|
|
1016
|
-
if (error.logs && Array.isArray(error.logs)) {
|
|
1017
|
-
errorMessage = error.logs.map(formatBunLog).join("\n\n");
|
|
1018
|
-
} else {
|
|
1019
|
-
errorMessage = String(error);
|
|
1020
|
-
}
|
|
1021
|
-
} else {
|
|
1022
|
-
errorMessage = String(error);
|
|
1023
|
-
}
|
|
1024
|
-
if (errorMessage === "Bundle failed" || errorMessage.includes("Bundle failed\n")) {
|
|
1025
|
-
try {
|
|
1026
|
-
const inspected = inspect(error);
|
|
1027
|
-
if (inspected && inspected !== "[object Object]" && inspected.length > errorMessage.length) {
|
|
1028
|
-
errorMessage = inspected;
|
|
1029
|
-
}
|
|
1030
|
-
} catch {
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
console.error(`\u274C Error building ${basePath}:`, error);
|
|
1034
|
-
buildErrors.push({
|
|
1035
|
-
file: `pages/${file}`,
|
|
1036
|
-
message: errorMessage,
|
|
1037
|
-
type: errorMessage.includes("minification") || errorMessage.includes("minify") ? "minify" : "render"
|
|
1038
|
-
});
|
|
1039
|
-
errorCount++;
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
const templatesDir = projectPaths.templates();
|
|
1043
|
-
const staticCollections = /* @__PURE__ */ new Map();
|
|
1044
|
-
const cmsResult = await buildCMSTemplates(
|
|
1045
|
-
templatesDir,
|
|
1046
|
-
globalComponents,
|
|
1047
|
-
i18nConfig,
|
|
1048
|
-
slugMappings,
|
|
1049
|
-
distDir,
|
|
1050
|
-
cmsService,
|
|
1051
|
-
generatedUrls,
|
|
1052
|
-
staticCollections,
|
|
1053
|
-
siteUrl,
|
|
1054
|
-
trackingScript
|
|
1055
|
-
);
|
|
1056
|
-
successCount += cmsResult.success;
|
|
1057
|
-
errorCount += cmsResult.errors;
|
|
1058
|
-
await generateStaticDataFiles(staticCollections, distDir);
|
|
1059
|
-
if (runningExperiments.length > 0) {
|
|
1060
|
-
await generateABFunctions(runningExperiments, distDir);
|
|
1061
|
-
console.log(`
|
|
1062
|
-
\u{1F9EA} A/B testing functions generated (middleware, tracker, results API)`);
|
|
1063
|
-
}
|
|
1064
|
-
if (siteUrl) {
|
|
1065
|
-
await generateRobotsTxt(siteUrl, distDir);
|
|
1066
|
-
await generateSitemap([...generatedUrls], siteUrl, distDir);
|
|
1067
|
-
console.log(`
|
|
1068
|
-
\u{1F50D} SEO files generated (robots.txt, sitemap.xml)`);
|
|
1069
|
-
} else {
|
|
1070
|
-
console.warn(`
|
|
1071
|
-
\u26A0\uFE0F Skipping SEO files: siteUrl not configured in project.config.json`);
|
|
1072
|
-
}
|
|
1073
|
-
console.log("\n" + "=".repeat(50));
|
|
1074
|
-
console.log(`\u2728 Build complete!`);
|
|
1075
|
-
console.log(` \u2705 Success: ${successCount}`);
|
|
1076
|
-
if (errorCount > 0) {
|
|
1077
|
-
console.log(` \u274C Errors: ${errorCount}`);
|
|
1078
|
-
}
|
|
1079
|
-
console.log(`
|
|
1080
|
-
\u{1F4E6} Production files in /dist:`);
|
|
1081
|
-
console.log(` - *.html (Static pages with vanilla JS)`);
|
|
1082
|
-
console.log(` - fonts/ (Custom fonts)`);
|
|
1083
|
-
console.log(` - images/ (Image assets)`);
|
|
1084
|
-
console.log(` - icons/ (Favicon and icons)`);
|
|
1085
|
-
if (staticCollections.size > 0) {
|
|
1086
|
-
console.log(` - data/ (CMS collection data for client filtering)`);
|
|
1087
|
-
}
|
|
1088
|
-
if (existsSync(functionsDir)) {
|
|
1089
|
-
console.log(` - functions/ (Cloudflare Pages Functions)`);
|
|
1090
|
-
}
|
|
1091
|
-
if (runningExperiments.length > 0) {
|
|
1092
|
-
console.log(` - A/B testing (middleware + tracking injected)`);
|
|
1093
|
-
}
|
|
1094
|
-
if (siteUrl) {
|
|
1095
|
-
console.log(` - robots.txt, sitemap.xml (SEO)`);
|
|
1096
|
-
}
|
|
1097
|
-
console.log(` - No React, no client-router \u2713`);
|
|
1098
|
-
const jsErrors = getJSValidationErrors();
|
|
1099
|
-
for (const { component, error } of jsErrors) {
|
|
1100
|
-
buildErrors.push({
|
|
1101
|
-
file: `components/${component}`,
|
|
1102
|
-
message: error,
|
|
1103
|
-
type: "minify"
|
|
1104
|
-
});
|
|
1105
|
-
}
|
|
1106
|
-
if (buildErrors.length > 0) {
|
|
1107
|
-
const seenMessages = /* @__PURE__ */ new Set();
|
|
1108
|
-
const uniqueErrors = buildErrors.filter((err) => {
|
|
1109
|
-
if (seenMessages.has(err.message)) return false;
|
|
1110
|
-
seenMessages.add(err.message);
|
|
1111
|
-
return true;
|
|
1112
|
-
});
|
|
1113
|
-
const errorsData = {
|
|
1114
|
-
errors: uniqueErrors,
|
|
1115
|
-
timestamp: Date.now()
|
|
1116
|
-
};
|
|
1117
|
-
await writeFile(errorsPath, JSON.stringify(errorsData, null, 2), "utf-8");
|
|
1118
|
-
const countMsg = uniqueErrors.length === buildErrors.length ? `${uniqueErrors.length} error${uniqueErrors.length === 1 ? "" : "s"}` : `${uniqueErrors.length} unique error${uniqueErrors.length === 1 ? "" : "s"} (affected ${buildErrors.length} files)`;
|
|
1119
|
-
console.log(`
|
|
1120
|
-
\u26A0\uFE0F Build errors written to dist/_errors.json (${countMsg})`);
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
export {
|
|
1125
|
-
hashContent,
|
|
1126
|
-
formatBunLog,
|
|
1127
|
-
getLocalizedOutputPath,
|
|
1128
|
-
getDisplayPath,
|
|
1129
|
-
generateRobotsTxt,
|
|
1130
|
-
generateSitemap,
|
|
1131
|
-
isCMSPage,
|
|
1132
|
-
buildCMSItemPath,
|
|
1133
|
-
injectTrackingScript,
|
|
1134
|
-
buildStaticPages
|
|
1135
|
-
};
|
|
1136
|
-
//# sourceMappingURL=chunk-JGP5A3Y5.js.map
|