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,19 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Maps CSS property values to utility class names
|
|
3
|
-
* Example: { padding: "10px", display: "flex" } → ["p-10px", "flex"]
|
|
2
|
+
* Maps CSS property values to Tailwind-style utility class names
|
|
3
|
+
* Example: { padding: "10px", display: "flex" } → ["p-[10px]", "flex"]
|
|
4
4
|
* Uses centralized configuration from utilityClassConfig.ts
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { ResponsiveStyleObject, StyleObject, StyleMapping } from './types';
|
|
7
|
+
import type { ResponsiveStyleObject, StyleObject, StyleMapping, StyleValue } from './types';
|
|
8
|
+
import { isResponsiveStyle } from './styleUtils';
|
|
8
9
|
import {
|
|
9
10
|
propertyMap,
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
propertyOrder,
|
|
12
|
+
staticUtilities,
|
|
13
|
+
staticUtilityReverse,
|
|
14
|
+
presetClassReverse,
|
|
15
|
+
keywordValues,
|
|
16
|
+
genericKeywordRoots,
|
|
17
|
+
integerValueRoots,
|
|
18
|
+
colorTokenProps,
|
|
12
19
|
shadowPresets,
|
|
13
20
|
gradientPresets,
|
|
14
21
|
borderPresets,
|
|
22
|
+
SPACING_SCALE_ROOTS,
|
|
23
|
+
SPACING_SCALE_REVERSE,
|
|
15
24
|
} from './utilityClassConfig';
|
|
16
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
camelToKebab,
|
|
27
|
+
cssPropertyToCamel,
|
|
28
|
+
encodeArbitraryValue,
|
|
29
|
+
parseUtilityClass,
|
|
30
|
+
splitVariantPrefix,
|
|
31
|
+
breakpointClassPrefix,
|
|
32
|
+
normalizeBreakpointVariant,
|
|
33
|
+
resolveRootProperty,
|
|
34
|
+
ROOT_CAMEL_OVERRIDES,
|
|
35
|
+
isBareColorTokenName,
|
|
36
|
+
} from './utilityClassNames';
|
|
37
|
+
import { registerStyleValue, registerDynamicStyle, getStyleValue, getDynamicStyle } from './styleValueRegistry';
|
|
17
38
|
import {
|
|
18
39
|
SCALABLE_CSS_PROPERTIES,
|
|
19
40
|
buildFluidClampWithExplicitMin,
|
|
@@ -22,43 +43,13 @@ import {
|
|
|
22
43
|
type ResponsiveScales,
|
|
23
44
|
} from './responsiveScaling';
|
|
24
45
|
|
|
25
|
-
// Function name abbreviations for shorter class names
|
|
26
|
-
const functionAbbreviations: Record<string, string> = {
|
|
27
|
-
blur: 'bl',
|
|
28
|
-
translateY: 'ty',
|
|
29
|
-
translateX: 'tx',
|
|
30
|
-
translate: 't',
|
|
31
|
-
scale: 'sc',
|
|
32
|
-
scaleX: 'scx',
|
|
33
|
-
scaleY: 'scy',
|
|
34
|
-
rotate: 'ro',
|
|
35
|
-
skew: 'sk',
|
|
36
|
-
skewX: 'skx',
|
|
37
|
-
skewY: 'sky',
|
|
38
|
-
repeat: 're',
|
|
39
|
-
minmax: 'mm',
|
|
40
|
-
calc: 'ca',
|
|
41
|
-
};
|
|
42
|
-
|
|
43
46
|
/**
|
|
44
47
|
* Check if a value is a StyleMapping object
|
|
45
48
|
*/
|
|
46
49
|
function isStyleMapping(value: unknown): value is StyleMapping {
|
|
47
|
-
return
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Sanitize a value for use in a CSS class name
|
|
52
|
-
* Replaces special characters with safe alternatives
|
|
53
|
-
*/
|
|
54
|
-
function sanitizeClassValue(value: string): string {
|
|
55
|
-
return value
|
|
56
|
-
.replace(/\s+/g, '-') // spaces to hyphens
|
|
57
|
-
.replace(/[()]/g, '') // remove parentheses
|
|
58
|
-
.replace(/,/g, '_') // commas to underscores
|
|
59
|
-
.replace(/%/g, 'p') // percent to 'p'
|
|
60
|
-
.replace(/\./g, 'd') // dots to 'd' (for decimals)
|
|
61
|
-
.replace(/[^\w-]/g, ''); // remove other special chars
|
|
50
|
+
return (
|
|
51
|
+
typeof value === 'object' && value !== null && '_mapping' in value && (value as StyleMapping)._mapping === true
|
|
52
|
+
);
|
|
62
53
|
}
|
|
63
54
|
|
|
64
55
|
/**
|
|
@@ -76,166 +67,184 @@ function shortHash(input: string): string {
|
|
|
76
67
|
}
|
|
77
68
|
|
|
78
69
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
70
|
+
* Whether the natural `root-(--x)` / `root-[value]` form would round-trip to a DIFFERENT property
|
|
71
|
+
* than `prop`. Roots shared by a shorthand and a color/width longhand (`border` → border/borderColor,
|
|
72
|
+
* `outline` → outline/outlineWidth/outlineColor) are disambiguated on parse by value type via
|
|
73
|
+
* `resolveRootProperty` — so a color-looking value (notably any opaque `var(--x)`) bound to the
|
|
74
|
+
* SHORTHAND reads back as the color longhand. Callers fall back to the explicit arbitrary-property
|
|
75
|
+
* form (`[border:var(--x)]`) when this returns true.
|
|
76
|
+
*
|
|
77
|
+
* Mirrors the inverse parser's property derivation EXACTLY (`classToStyle`): `ROOT_CAMEL_OVERRIDES`
|
|
78
|
+
* wins first (px → paddingInline, …), else `resolveRootProperty`. Comparing kebab CSS names instead
|
|
79
|
+
* would false-positive on those overridden roots (`px` resolves to `padding`, not `padding-inline`).
|
|
87
80
|
*/
|
|
88
|
-
function
|
|
89
|
-
|
|
81
|
+
function rootFormMisresolves(root: string, prop: string, value: string): boolean {
|
|
82
|
+
const parsedProp = ROOT_CAMEL_OVERRIDES[root] ?? cssPropertyToCamel(resolveRootProperty(root, value));
|
|
83
|
+
return parsedProp !== prop;
|
|
90
84
|
}
|
|
91
85
|
|
|
92
86
|
/**
|
|
93
|
-
* Converts a CSS property value to a utility class name
|
|
94
|
-
*
|
|
87
|
+
* Converts a CSS property value to a Tailwind-style utility class name.
|
|
88
|
+
* Examples:
|
|
89
|
+
* { prop: "padding", value: "16px" } → "p-4" (exact scale step)
|
|
90
|
+
* { prop: "padding", value: "13px" } → "p-[13px]" (off-scale → arbitrary)
|
|
91
|
+
* { prop: "display", value: "flex" } → "flex"
|
|
92
|
+
* { prop: "color", value: "primary" } → "text-primary"
|
|
93
|
+
* { prop: "width", value: "100%" } → "w-full"
|
|
94
|
+
* { prop: "textOverflow", value: "ellipsis" } → "[text-overflow:ellipsis]"
|
|
95
95
|
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
96
|
+
* Values that can't be encoded reversibly fall back to a hash class
|
|
97
|
+
* (`pt-h1y9pr6i`) resolved through the style-value registry.
|
|
98
98
|
*/
|
|
99
99
|
function propertyValueToClass(prop: string, value: string | number): string | null {
|
|
100
|
-
const prefix = propertyMap[prop];
|
|
101
|
-
|
|
102
|
-
// For properties not in propertyMap, generate a dynamic fallback class
|
|
103
|
-
if (!prefix) {
|
|
104
|
-
const stringValue = String(value);
|
|
105
|
-
// Generate a short prefix from the property name (first 2-4 chars of each word)
|
|
106
|
-
// e.g., "textOverflow" → "txov", "WebkitBackgroundClip" → "wbbg"
|
|
107
|
-
const dynamicPrefix = prop
|
|
108
|
-
.replace(/([A-Z])/g, '-$1') // camelCase to kebab
|
|
109
|
-
.toLowerCase()
|
|
110
|
-
.split('-')
|
|
111
|
-
.filter(Boolean)
|
|
112
|
-
.map(word => word.slice(0, 2)) // first 2 chars of each word
|
|
113
|
-
.join('');
|
|
114
|
-
|
|
115
|
-
// Sanitize value for class name
|
|
116
|
-
const sanitizedValue = sanitizeClassValue(stringValue);
|
|
117
|
-
const className = `${dynamicPrefix}-${sanitizedValue}`;
|
|
118
|
-
|
|
119
|
-
// Convert camelCase to kebab-case for CSS property
|
|
120
|
-
const cssProperty = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
121
|
-
|
|
122
|
-
// Register in dynamic registry with property info
|
|
123
|
-
registerDynamicStyle(className, cssProperty, value);
|
|
124
|
-
return className;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
100
|
let stringValue = String(value);
|
|
128
101
|
|
|
129
102
|
// Strip outer quotes from fontFamily values (e.g. "Space Grotesk" → Space Grotesk)
|
|
130
103
|
if (prop === 'fontFamily') {
|
|
131
|
-
stringValue = stringValue
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
104
|
+
stringValue = stringValue
|
|
105
|
+
.split(',')
|
|
106
|
+
.map((font) => {
|
|
107
|
+
const trimmed = font.trim();
|
|
108
|
+
if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
|
|
109
|
+
return trimmed.slice(1, -1);
|
|
110
|
+
}
|
|
111
|
+
return trimmed;
|
|
112
|
+
})
|
|
113
|
+
.join(', ');
|
|
139
114
|
}
|
|
140
115
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (mapping[stringValue]) {
|
|
147
|
-
className = mapping[stringValue];
|
|
148
|
-
}
|
|
116
|
+
// Static utilities (Tailwind names): display: flex → "flex", textAlign: center → "text-center"
|
|
117
|
+
const staticClass = staticUtilities[prop]?.[stringValue];
|
|
118
|
+
if (staticClass) {
|
|
119
|
+
registerStyleValue(staticClass, stringValue);
|
|
120
|
+
return staticClass;
|
|
149
121
|
}
|
|
150
122
|
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
123
|
+
// Preset values (e.g., boxShadow: "2" → shadow-2)
|
|
124
|
+
const shadowPreset = shadowPresets[stringValue];
|
|
125
|
+
if (prop === 'boxShadow' && shadowPreset) {
|
|
126
|
+
const className = `shadow-${stringValue}`;
|
|
127
|
+
registerStyleValue(className, shadowPreset);
|
|
128
|
+
return className;
|
|
154
129
|
}
|
|
155
|
-
|
|
156
|
-
|
|
130
|
+
const gradientPreset = gradientPresets[stringValue];
|
|
131
|
+
if ((prop === 'background' || prop === 'backgroundImage') && gradientPreset) {
|
|
132
|
+
const className = `bg-gradient-${stringValue}`;
|
|
133
|
+
registerStyleValue(className, gradientPreset);
|
|
134
|
+
return className;
|
|
157
135
|
}
|
|
158
|
-
|
|
159
|
-
|
|
136
|
+
const borderPreset = borderPresets[stringValue];
|
|
137
|
+
if (prop === 'border' && borderPreset) {
|
|
138
|
+
const className = `border-preset-${stringValue}`;
|
|
139
|
+
registerStyleValue(className, borderPreset);
|
|
140
|
+
return className;
|
|
160
141
|
}
|
|
161
142
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
.replace(/-(\d)/g, 'n$1') // "-15px" → "n15px"
|
|
173
|
-
.replace(/px$/i, '') // Remove trailing px for brevity
|
|
174
|
-
.replace(/%$/, 'p'); // "50%" → "50p"
|
|
175
|
-
className = `${prefix}-${abbrev}${argNormalized}`;
|
|
176
|
-
}
|
|
143
|
+
const root = propertyMap[prop];
|
|
144
|
+
|
|
145
|
+
// Properties without a Tailwind root use arbitrary-property syntax:
|
|
146
|
+
// textOverflow: ellipsis → "[text-overflow:ellipsis]"
|
|
147
|
+
if (!root) {
|
|
148
|
+
const cssProperty = camelToKebab(prop);
|
|
149
|
+
const encoded = encodeArbitraryValue(stringValue);
|
|
150
|
+
const className = encoded != null ? `[${cssProperty}:${encoded}]` : `${cssProperty}-h${shortHash(stringValue)}`;
|
|
151
|
+
registerDynamicStyle(className, cssProperty, value);
|
|
152
|
+
return className;
|
|
177
153
|
}
|
|
178
154
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
155
|
+
let className: string | null = null;
|
|
156
|
+
|
|
157
|
+
// Named keyword values: width: 100% → w-full, margin: auto → m-auto
|
|
158
|
+
const kwTable = keywordValues[root];
|
|
159
|
+
if (kwTable) {
|
|
160
|
+
for (const [keyword, cssValue] of Object.entries(kwTable)) {
|
|
161
|
+
if (cssValue === stringValue) {
|
|
162
|
+
className = `${root}-${keyword}`;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
185
165
|
}
|
|
186
166
|
}
|
|
187
167
|
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
(prop === 'color' || prop === 'backgroundColor' || prop === 'borderColor') &&
|
|
192
|
-
!stringValue.match(/^\d/) && !stringValue.includes('#') && !stringValue.includes('rgb')) {
|
|
193
|
-
className = `${prefix}-${stringValue}`;
|
|
168
|
+
// Generic keyword roots: cursor: pointer → cursor-pointer, transformOrigin: center → origin-center
|
|
169
|
+
if (!className && genericKeywordRoots.has(root) && /^[a-z][a-z-]*$/.test(stringValue)) {
|
|
170
|
+
className = `${root}-${stringValue}`;
|
|
194
171
|
}
|
|
195
172
|
|
|
196
|
-
//
|
|
197
|
-
if (!className &&
|
|
198
|
-
className = `${
|
|
173
|
+
// Bare numeric values Tailwind-style: zIndex: 10 → z-10, opacity: 0.5 → opacity-50
|
|
174
|
+
if (!className && integerValueRoots.has(root) && /^-?\d+$/.test(stringValue)) {
|
|
175
|
+
className = `${root}-${stringValue}`;
|
|
199
176
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
177
|
+
if (!className && prop === 'opacity') {
|
|
178
|
+
const num = Number(stringValue);
|
|
179
|
+
if (Number.isFinite(num) && num >= 0 && num <= 1) {
|
|
180
|
+
const scaled = Math.round(num * 100);
|
|
181
|
+
if (Math.abs(num * 100 - scaled) < 1e-9) {
|
|
182
|
+
className = `opacity-${scaled}`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
205
185
|
}
|
|
206
186
|
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
187
|
+
// Named spacing scale (Tailwind steps): padding 16px → p-4, gap 24px → gap-6.
|
|
188
|
+
// Only EXACT steps; off-scale values fall through to the arbitrary form below.
|
|
189
|
+
// Keyword values (w-full, m-auto) are matched above, so they still win.
|
|
190
|
+
if (!className && SPACING_SCALE_ROOTS.has(root)) {
|
|
191
|
+
const step = SPACING_SCALE_REVERSE[stringValue];
|
|
192
|
+
if (step !== undefined) {
|
|
193
|
+
className = `${root}-${step}`;
|
|
194
|
+
}
|
|
211
195
|
}
|
|
212
196
|
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
|
|
197
|
+
// CSS variables: var(--x) → root-(--x). The `font-*` root is shared by font-weight and
|
|
198
|
+
// font-family and is disambiguated by value type — but a `var(--x)` value is ambiguous, so
|
|
199
|
+
// weight/size vars carry a Tailwind data-type hint (`number:` / `length:`) the parser reads
|
|
200
|
+
// back. Without it a `fontWeight: var(--h-fw)` binding would resolve to `font-family` (an
|
|
201
|
+
// invalid `font-family: 450`), dropping the weight entirely.
|
|
202
|
+
if (!className) {
|
|
203
|
+
const varMatch = stringValue.match(/^var\((--[\w-]+)\)$/);
|
|
204
|
+
if (varMatch) {
|
|
205
|
+
const varName = (varMatch[1] ?? '').slice(2); // strip the leading `--`
|
|
206
|
+
if (prop === 'fontSize') className = `text-(length:${varMatch[1]})`;
|
|
207
|
+
else if (prop === 'fontWeight') className = `font-(number:${varMatch[1]})`;
|
|
208
|
+
// The `border`/`outline` roots are shared by a shorthand and a color longhand
|
|
209
|
+
// (`border` vs `borderColor`). The inverse parser disambiguates by value type, but a
|
|
210
|
+
// `var(--x)` value is opaque and reads as a color — so `border-(--x)` would round-trip
|
|
211
|
+
// to `borderColor`. When the prop is the shorthand/width longhand, fall back to the
|
|
212
|
+
// unambiguous arbitrary-property form (`[border:var(--x)]`), which names it explicitly.
|
|
213
|
+
else if (rootFormMisresolves(root, prop, stringValue)) {
|
|
214
|
+
className = `[${camelToKebab(prop)}:${stringValue}]`;
|
|
215
|
+
}
|
|
216
|
+
// A `var(--token)` on a color-token prop IS a Meno token reference → emit the bare token
|
|
217
|
+
// form (`bg-muted`), matching the bare-value path so `var(--muted)` and `muted` agree.
|
|
218
|
+
// (Token-aware inverse recovers it; palette-shaped names fall through to the var shorthand.)
|
|
219
|
+
else if (colorTokenProps.has(prop) && isBareColorTokenName(varName)) {
|
|
220
|
+
className = `${root}-${varName}`;
|
|
221
|
+
} else className = `${root}-(${varMatch[1]})`;
|
|
222
|
+
}
|
|
216
223
|
}
|
|
217
224
|
|
|
218
|
-
//
|
|
219
|
-
if (!className &&
|
|
220
|
-
|
|
221
|
-
className = `${prefix}-${slashValue}`;
|
|
225
|
+
// Bare color tokens (Meno convention): color: "primary" → text-primary
|
|
226
|
+
if (!className && colorTokenProps.has(prop) && isBareColorTokenName(stringValue)) {
|
|
227
|
+
className = `${root}-${stringValue}`;
|
|
222
228
|
}
|
|
223
229
|
|
|
224
|
-
//
|
|
230
|
+
// Arbitrary value (Tailwind bracket syntax): padding: "92px 0" → p-[92px_0]
|
|
225
231
|
if (!className) {
|
|
226
|
-
|
|
232
|
+
const encoded = encodeArbitraryValue(stringValue);
|
|
233
|
+
if (encoded != null) {
|
|
234
|
+
// Same shorthand/longhand guard as the var branch: a bare color value bound to the
|
|
235
|
+
// `border`/`outline` shorthand would parse back as the color longhand, so name the
|
|
236
|
+
// property explicitly via the arbitrary-property form instead of `root-[…]`.
|
|
237
|
+
className = rootFormMisresolves(root, prop, stringValue)
|
|
238
|
+
? `[${camelToKebab(prop)}:${encoded}]`
|
|
239
|
+
: `${root}-[${encoded}]`;
|
|
240
|
+
}
|
|
227
241
|
}
|
|
228
242
|
|
|
229
|
-
// Hash-fallback for
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
// (paddings collapse to 0, etc.). Short FNV-1a hash + style-value
|
|
235
|
-
// registry preserves the original value for the CSS generator without
|
|
236
|
-
// baking it into the selector.
|
|
237
|
-
if (hasIllegalClassChars(className)) {
|
|
238
|
-
className = `${prefix}-h${shortHash(stringValue)}`;
|
|
243
|
+
// Hash-fallback for values that can't be encoded reversibly (quotes,
|
|
244
|
+
// brackets, literal underscores). The original value is preserved in the
|
|
245
|
+
// style-value registry for the CSS generator.
|
|
246
|
+
if (!className) {
|
|
247
|
+
className = `${root}-h${shortHash(stringValue)}`;
|
|
239
248
|
}
|
|
240
249
|
|
|
241
250
|
// Register original value for CSS generation (single registration point)
|
|
@@ -243,24 +252,19 @@ function propertyValueToClass(prop: string, value: string | number): string | nu
|
|
|
243
252
|
return className;
|
|
244
253
|
}
|
|
245
254
|
|
|
246
|
-
// Get property order from propertyMap for consistent class ordering
|
|
247
|
-
const propertyOrder = Object.keys(propertyMap);
|
|
248
|
-
|
|
249
255
|
/**
|
|
250
256
|
* Convert a style object to an array of utility classes
|
|
251
|
-
* Example: { padding: "10px", display: "flex" } → ["p-10px", "flex"]
|
|
257
|
+
* Example: { padding: "10px", display: "flex" } → ["p-[10px]", "flex"]
|
|
252
258
|
*
|
|
253
|
-
* Properties are sorted according to
|
|
259
|
+
* Properties are sorted according to propertyOrder to ensure
|
|
254
260
|
* dependent properties (like borderColor) come after their base (border)
|
|
255
261
|
*
|
|
256
262
|
* StyleMapping values are filtered out - they are handled at render time
|
|
257
263
|
*/
|
|
258
|
-
export function stylesToClasses(
|
|
259
|
-
styles: StyleObject | Record<string, string | number> | null | undefined
|
|
260
|
-
): string[] {
|
|
264
|
+
export function stylesToClasses(styles: StyleObject | Record<string, string | number> | null | undefined): string[] {
|
|
261
265
|
if (!styles) return [];
|
|
262
266
|
|
|
263
|
-
// Sort properties by their order
|
|
267
|
+
// Sort properties by their canonical order
|
|
264
268
|
// This ensures border comes before borderColor, etc.
|
|
265
269
|
const sortedProps = Object.keys(styles).sort((a, b) => {
|
|
266
270
|
const indexA = propertyOrder.indexOf(a);
|
|
@@ -274,6 +278,7 @@ export function stylesToClasses(
|
|
|
274
278
|
const classes: string[] = [];
|
|
275
279
|
for (const prop of sortedProps) {
|
|
276
280
|
const value = styles[prop];
|
|
281
|
+
if (value === undefined) continue;
|
|
277
282
|
// Skip StyleMapping values - they are resolved at render time, not converted to classes
|
|
278
283
|
if (isStyleMapping(value)) continue;
|
|
279
284
|
const className = propertyValueToClass(prop, value);
|
|
@@ -287,10 +292,10 @@ export function stylesToClasses(
|
|
|
287
292
|
/**
|
|
288
293
|
* Convert a responsive style object to utility classes with responsive prefixes
|
|
289
294
|
* Example: { base: { padding: "10px" }, tablet: { padding: "24px" } }
|
|
290
|
-
* → ["p-10px", "
|
|
295
|
+
* → ["p-[10px]", "tablet:p-[24px]"]
|
|
291
296
|
*
|
|
292
297
|
* Also handles flat merged style objects:
|
|
293
|
-
* Example: { padding: "10px", display: "flex" } → ["p-10px", "flex"]
|
|
298
|
+
* Example: { padding: "10px", display: "flex" } → ["p-[10px]", "flex"]
|
|
294
299
|
*/
|
|
295
300
|
/** Values that don't make sense in a fluid container pattern. Mirrors cssGeneration.ts. */
|
|
296
301
|
const CONTAINER_RESERVED_VALUES = new Set(['auto', 'inherit', 'initial', 'unset', '']);
|
|
@@ -322,7 +327,7 @@ function transformContainerIntent(style: StyleObject): StyleObject {
|
|
|
322
327
|
* In fluid mode, consume per-node mobile overrides for scalable properties
|
|
323
328
|
* into the base's `clamp()` value. The mobile value becomes the clamp's MIN
|
|
324
329
|
* (small-viewport endpoint), the base stays as MAX. The mobile property is
|
|
325
|
-
* then stripped from the mobile slice so no
|
|
330
|
+
* then stripped from the mobile slice so no `mobile:*` @media rule is emitted
|
|
326
331
|
* for it — avoiding the jump at the mobile breakpoint that a hard override
|
|
327
332
|
* would create.
|
|
328
333
|
*
|
|
@@ -332,12 +337,12 @@ function transformContainerIntent(style: StyleObject): StyleObject {
|
|
|
332
337
|
*
|
|
333
338
|
* Bails out when units mismatch, parsing fails, or the registered values
|
|
334
339
|
* aren't plain numeric+unit strings — those cases fall back to today's
|
|
335
|
-
* behavior (mobile emits its own
|
|
340
|
+
* behavior (mobile emits its own `mobile:*` rule).
|
|
336
341
|
*/
|
|
337
342
|
function consumeMobileIntoBaseClamp(
|
|
338
343
|
base: StyleObject,
|
|
339
344
|
mobile: StyleObject,
|
|
340
|
-
responsiveScales: ResponsiveScales
|
|
345
|
+
responsiveScales: ResponsiveScales,
|
|
341
346
|
): { patchedBase: StyleObject; patchedMobile: StyleObject } {
|
|
342
347
|
const fluidRange = responsiveScales.fluidRange ?? DEFAULT_FLUID_RANGE;
|
|
343
348
|
const patchedBase: StyleObject = { ...base };
|
|
@@ -364,7 +369,7 @@ function consumeMobileIntoBaseClamp(
|
|
|
364
369
|
baseParsed.value,
|
|
365
370
|
baseParsed.unit,
|
|
366
371
|
fluidRange.min,
|
|
367
|
-
fluidRange.max
|
|
372
|
+
fluidRange.max,
|
|
368
373
|
);
|
|
369
374
|
|
|
370
375
|
patchedBase[prop] = clampValue;
|
|
@@ -376,7 +381,7 @@ function consumeMobileIntoBaseClamp(
|
|
|
376
381
|
|
|
377
382
|
export function responsiveStylesToClasses(
|
|
378
383
|
styles: StyleObject | ResponsiveStyleObject | null | undefined,
|
|
379
|
-
options?: { fluidActive?: boolean; responsiveScales?: ResponsiveScales }
|
|
384
|
+
options?: { fluidActive?: boolean; responsiveScales?: ResponsiveScales },
|
|
380
385
|
): string[] {
|
|
381
386
|
if (!styles) return [];
|
|
382
387
|
const fluidActive = options?.fluidActive === true;
|
|
@@ -395,45 +400,35 @@ export function responsiveStylesToClasses(
|
|
|
395
400
|
let baseSource = responsiveStyles.base;
|
|
396
401
|
let mobileSource = responsiveStyles.mobile;
|
|
397
402
|
if (fluidActive && responsiveScales?.enabled === true && baseSource && mobileSource) {
|
|
398
|
-
const { patchedBase, patchedMobile } = consumeMobileIntoBaseClamp(
|
|
399
|
-
baseSource,
|
|
400
|
-
mobileSource,
|
|
401
|
-
responsiveScales
|
|
402
|
-
);
|
|
403
|
+
const { patchedBase, patchedMobile } = consumeMobileIntoBaseClamp(baseSource, mobileSource, responsiveScales);
|
|
403
404
|
baseSource = patchedBase;
|
|
404
405
|
mobileSource = patchedMobile;
|
|
405
406
|
}
|
|
406
407
|
|
|
407
408
|
// Base styles (no prefix)
|
|
408
409
|
if (baseSource) {
|
|
409
|
-
const base = fluidActive
|
|
410
|
-
? transformContainerIntent(baseSource)
|
|
411
|
-
: baseSource;
|
|
410
|
+
const base = fluidActive ? transformContainerIntent(baseSource) : baseSource;
|
|
412
411
|
classes.push(...stylesToClasses(base));
|
|
413
412
|
}
|
|
414
413
|
|
|
415
|
-
// Tablet styles (
|
|
414
|
+
// Tablet styles (tablet: variant prefix)
|
|
416
415
|
if (responsiveStyles.tablet) {
|
|
417
|
-
const tablet = fluidActive
|
|
418
|
-
? transformContainerIntent(responsiveStyles.tablet)
|
|
419
|
-
: responsiveStyles.tablet;
|
|
416
|
+
const tablet = fluidActive ? transformContainerIntent(responsiveStyles.tablet) : responsiveStyles.tablet;
|
|
420
417
|
const tabletClasses = stylesToClasses(tablet);
|
|
421
|
-
|
|
418
|
+
const prefix = breakpointClassPrefix('tablet');
|
|
419
|
+
classes.push(...tabletClasses.map((cls) => `${prefix}${cls}`));
|
|
422
420
|
}
|
|
423
421
|
|
|
424
|
-
// Mobile styles (
|
|
422
|
+
// Mobile styles (mobile: variant prefix)
|
|
425
423
|
if (mobileSource && Object.keys(mobileSource).length > 0) {
|
|
426
|
-
const mobile = fluidActive
|
|
427
|
-
? transformContainerIntent(mobileSource)
|
|
428
|
-
: mobileSource;
|
|
424
|
+
const mobile = fluidActive ? transformContainerIntent(mobileSource) : mobileSource;
|
|
429
425
|
const mobileClasses = stylesToClasses(mobile);
|
|
430
|
-
|
|
426
|
+
const prefix = breakpointClassPrefix('mobile');
|
|
427
|
+
classes.push(...mobileClasses.map((cls) => `${prefix}${cls}`));
|
|
431
428
|
}
|
|
432
429
|
} else {
|
|
433
430
|
// Flat style object - treat all as base classes
|
|
434
|
-
const flat = fluidActive
|
|
435
|
-
? transformContainerIntent(styles as StyleObject)
|
|
436
|
-
: (styles as StyleObject);
|
|
431
|
+
const flat = fluidActive ? transformContainerIntent(styles as StyleObject) : (styles as StyleObject);
|
|
437
432
|
classes.push(...stylesToClasses(flat));
|
|
438
433
|
}
|
|
439
434
|
|
|
@@ -442,57 +437,58 @@ export function responsiveStylesToClasses(
|
|
|
442
437
|
|
|
443
438
|
/**
|
|
444
439
|
* Parse a utility class back to CSS property and value
|
|
445
|
-
* Example: "p-10px" → { padding: "10px" }
|
|
440
|
+
* Example: "p-[10px]" → { prop: "padding", value: "10px" }
|
|
446
441
|
*/
|
|
447
|
-
export function classToStyle(
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
cleanClass = className.slice(4);
|
|
442
|
+
export function classToStyle(
|
|
443
|
+
className: string,
|
|
444
|
+
knownTokens?: ReadonlySet<string>,
|
|
445
|
+
): { prop: string; value: string } | null {
|
|
446
|
+
// Remove responsive variant prefix for parsing (tablet:p-[10px] → p-[10px])
|
|
447
|
+
const { base: cleanClass } = splitVariantPrefix(className);
|
|
448
|
+
|
|
449
|
+
// Static utilities and presets have fixed reverse mappings
|
|
450
|
+
if (staticUtilityReverse[cleanClass]) {
|
|
451
|
+
return staticUtilityReverse[cleanClass];
|
|
458
452
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
if (classToStyleSpecialCases[cleanClass]) {
|
|
462
|
-
return classToStyleSpecialCases[cleanClass];
|
|
453
|
+
if (presetClassReverse[cleanClass]) {
|
|
454
|
+
return presetClassReverse[cleanClass];
|
|
463
455
|
}
|
|
464
456
|
|
|
465
|
-
|
|
466
|
-
const match = cleanClass.match(/^([a-z-]+)-(.*?)$/);
|
|
467
|
-
if (!match) return null;
|
|
457
|
+
const parsed = parseUtilityClass(cleanClass, knownTokens);
|
|
468
458
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
if (val === prefix) {
|
|
475
|
-
prop = key;
|
|
476
|
-
break;
|
|
459
|
+
if (!parsed) {
|
|
460
|
+
// Dynamic (arbitrary-property hash) classes registered for unknown roots
|
|
461
|
+
const dynamic = getDynamicStyle(cleanClass);
|
|
462
|
+
if (dynamic) {
|
|
463
|
+
return { prop: cssPropertyToCamel(dynamic.property), value: String(dynamic.value) };
|
|
477
464
|
}
|
|
465
|
+
return null;
|
|
478
466
|
}
|
|
479
467
|
|
|
480
|
-
if (
|
|
468
|
+
if (parsed.kind === 'arbitrary-property') {
|
|
469
|
+
return { prop: cssPropertyToCamel(parsed.property), value: parsed.value! };
|
|
470
|
+
}
|
|
481
471
|
|
|
482
472
|
// Hash-fallback class — value is `h<base36>`, the real CSS value lives in
|
|
483
473
|
// the style-value registry (set when the class was minted from a complex
|
|
484
|
-
//
|
|
485
|
-
//
|
|
486
|
-
if (
|
|
474
|
+
// value that wouldn't fit in a class name). Pull the real value back out
|
|
475
|
+
// so editor reads see the original expression.
|
|
476
|
+
if (parsed.kind === 'hash') {
|
|
487
477
|
const registered = getStyleValue(cleanClass);
|
|
488
|
-
if (registered
|
|
489
|
-
|
|
490
|
-
|
|
478
|
+
if (registered == null) return null;
|
|
479
|
+
const value = String(registered);
|
|
480
|
+
const root = parsed.root!;
|
|
481
|
+
const prop = ROOT_CAMEL_OVERRIDES[root] ?? cssPropertyToCamel(resolveRootProperty(root, value));
|
|
482
|
+
return { prop, value };
|
|
491
483
|
}
|
|
492
484
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
485
|
+
const root = parsed.root;
|
|
486
|
+
const prop = root && ROOT_CAMEL_OVERRIDES[root] ? ROOT_CAMEL_OVERRIDES[root] : cssPropertyToCamel(parsed.property);
|
|
487
|
+
let value = parsed.value!;
|
|
488
|
+
|
|
489
|
+
// Color token props store bare tokens (var(--primary) → "primary")
|
|
490
|
+
if (parsed.kind === 'var' && colorTokenProps.has(prop)) {
|
|
491
|
+
value = value.replace(/^var\(--([\w-]+)\)$/, '$1');
|
|
496
492
|
}
|
|
497
493
|
|
|
498
494
|
return { prop, value };
|
|
@@ -500,24 +496,18 @@ export function classToStyle(className: string): { prop: string; value: string }
|
|
|
500
496
|
|
|
501
497
|
/**
|
|
502
498
|
* Convert utility classes back to a style object
|
|
503
|
-
* Example: ["p-10px", "
|
|
499
|
+
* Example: ["p-[10px]", "tablet:p-[24px]"] → { base: { padding: "10px" }, tablet: { padding: "24px" } }
|
|
504
500
|
*/
|
|
505
|
-
export function classesToStyles(classes: string[]): ResponsiveStyleObject | null {
|
|
501
|
+
export function classesToStyles(classes: string[], knownTokens?: ReadonlySet<string>): ResponsiveStyleObject | null {
|
|
506
502
|
const styles: ResponsiveStyleObject = { base: {}, tablet: {}, mobile: {} };
|
|
507
503
|
|
|
508
504
|
for (const className of classes) {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
breakpoint = 'tablet';
|
|
514
|
-
cleanClass = className.slice(2);
|
|
515
|
-
} else if (className.startsWith('mob-')) {
|
|
516
|
-
breakpoint = 'mobile';
|
|
517
|
-
cleanClass = className.slice(4);
|
|
518
|
-
}
|
|
505
|
+
const { breakpoint: variant, base: cleanClass } = splitVariantPrefix(className);
|
|
506
|
+
// Accept both the current desktop-first form (`max-tablet:`) and the legacy bare form (`tablet:`).
|
|
507
|
+
const bp = normalizeBreakpointVariant(variant);
|
|
508
|
+
const breakpoint: 'base' | 'tablet' | 'mobile' = bp === 'tablet' ? 'tablet' : bp === 'mobile' ? 'mobile' : 'base';
|
|
519
509
|
|
|
520
|
-
const styleEntry = classToStyle(cleanClass);
|
|
510
|
+
const styleEntry = classToStyle(cleanClass, knownTokens);
|
|
521
511
|
if (styleEntry) {
|
|
522
512
|
if (!styles[breakpoint]) {
|
|
523
513
|
styles[breakpoint] = {};
|
|
@@ -530,5 +520,88 @@ export function classesToStyles(classes: string[]): ResponsiveStyleObject | null
|
|
|
530
520
|
if (Object.keys(styles.tablet || {}).length === 0) delete styles.tablet;
|
|
531
521
|
if (Object.keys(styles.mobile || {}).length === 0) delete styles.mobile;
|
|
532
522
|
|
|
533
|
-
|
|
523
|
+
// Return the object when ANY breakpoint carries a declaration — not only base. A class string
|
|
524
|
+
// can legitimately style just a narrower breakpoint (e.g. "tablet:p-[16px]"), and dropping it to
|
|
525
|
+
// null there would lose class-string styling for that node (class-styling adapter, §11).
|
|
526
|
+
const hasAny =
|
|
527
|
+
Object.keys(styles.base || {}).length > 0 ||
|
|
528
|
+
Object.keys(styles.tablet || {}).length > 0 ||
|
|
529
|
+
Object.keys(styles.mobile || {}).length > 0;
|
|
530
|
+
return hasAny ? styles : null;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Whether a single style value can be stored as a STATIC utility class. Static strings (no
|
|
535
|
+
* `{{template}}`) and numbers can; template-bearing strings and `_mapping` objects cannot — a
|
|
536
|
+
* template would mint a broken `p-[{{x}}px]`, and a mapping is prop-driven. The latter must stay in
|
|
537
|
+
* the `style` object (rendered via the runtime var-bridge / `class:list`). This is the boundary that
|
|
538
|
+
* lets styling default to class storage while keeping dynamic values correct.
|
|
539
|
+
*/
|
|
540
|
+
export function isClassableStyleValue(value: unknown): boolean {
|
|
541
|
+
if (typeof value === 'number') return true;
|
|
542
|
+
if (typeof value === 'string') return !value.includes('{{');
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function splitStyleBucket(bucket: StyleObject): {
|
|
547
|
+
classable: StyleObject;
|
|
548
|
+
residual: StyleObject;
|
|
549
|
+
} {
|
|
550
|
+
const classable: StyleObject = {};
|
|
551
|
+
const residual: StyleObject = {};
|
|
552
|
+
for (const [k, v] of Object.entries(bucket)) {
|
|
553
|
+
if (isClassableStyleValue(v)) classable[k] = v as string | number;
|
|
554
|
+
else residual[k] = v as StyleMapping;
|
|
555
|
+
}
|
|
556
|
+
return { classable, residual };
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Split a style value into the part storable as a utility-class string (static values) and the
|
|
561
|
+
* residual that must stay in the `style` object (templates + `_mapping`s). Preserves the responsive
|
|
562
|
+
* shape; a flat object is treated as `base`. Either side is null when it has no declarations. The
|
|
563
|
+
* canonical home (shared by the studio persistence boundary and the project-wide migration) for the
|
|
564
|
+
* "what can be a class" decision.
|
|
565
|
+
*/
|
|
566
|
+
export function splitStyleByClassability(style: StyleValue | null | undefined): {
|
|
567
|
+
classable: ResponsiveStyleObject | null;
|
|
568
|
+
residual: ResponsiveStyleObject | null;
|
|
569
|
+
} {
|
|
570
|
+
if (!style || typeof style !== 'object') return { classable: null, residual: null };
|
|
571
|
+
|
|
572
|
+
if (isResponsiveStyle(style)) {
|
|
573
|
+
const classable: ResponsiveStyleObject = {};
|
|
574
|
+
const residual: ResponsiveStyleObject = {};
|
|
575
|
+
for (const [bp, bucket] of Object.entries(style)) {
|
|
576
|
+
if (!bucket || typeof bucket !== 'object') continue;
|
|
577
|
+
const split = splitStyleBucket(bucket);
|
|
578
|
+
if (Object.keys(split.classable).length > 0) classable[bp] = split.classable;
|
|
579
|
+
if (Object.keys(split.residual).length > 0) residual[bp] = split.residual;
|
|
580
|
+
}
|
|
581
|
+
return {
|
|
582
|
+
classable: Object.keys(classable).length > 0 ? classable : null,
|
|
583
|
+
residual: Object.keys(residual).length > 0 ? residual : null,
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const split = splitStyleBucket(style as StyleObject);
|
|
588
|
+
return {
|
|
589
|
+
classable: Object.keys(split.classable).length > 0 ? { base: split.classable } : null,
|
|
590
|
+
residual: Object.keys(split.residual).length > 0 ? { base: split.residual } : null,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Whether a style value contains at least one prop `_mapping` (in any breakpoint) — flat or
|
|
596
|
+
* responsive. Prop-driven styling can't be a static utility class, so callers that gate class
|
|
597
|
+
* conversion (the studio panel, the project migration) check this. Single source of truth.
|
|
598
|
+
*/
|
|
599
|
+
export function styleHasMapping(style: StyleValue | null | undefined): boolean {
|
|
600
|
+
if (!style || typeof style !== 'object') return false;
|
|
601
|
+
const buckets = isResponsiveStyle(style) ? Object.values(style) : [style as Record<string, unknown>];
|
|
602
|
+
for (const bucket of buckets) {
|
|
603
|
+
if (!bucket || typeof bucket !== 'object') continue;
|
|
604
|
+
for (const v of Object.values(bucket)) if (isStyleMapping(v)) return true;
|
|
605
|
+
}
|
|
606
|
+
return false;
|
|
534
607
|
}
|