@obra-studio/figma-console-mcp 1.32.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/LICENSE +21 -0
- package/README.md +879 -0
- package/dist/apps/design-system-dashboard/scoring/accessibility.d.ts +14 -0
- package/dist/apps/design-system-dashboard/scoring/accessibility.d.ts.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/accessibility.js +278 -0
- package/dist/apps/design-system-dashboard/scoring/accessibility.js.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/component-metadata.d.ts +29 -0
- package/dist/apps/design-system-dashboard/scoring/component-metadata.d.ts.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/component-metadata.js +358 -0
- package/dist/apps/design-system-dashboard/scoring/component-metadata.js.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/consistency.d.ts +14 -0
- package/dist/apps/design-system-dashboard/scoring/consistency.d.ts.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/consistency.js +342 -0
- package/dist/apps/design-system-dashboard/scoring/consistency.js.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/coverage.d.ts +14 -0
- package/dist/apps/design-system-dashboard/scoring/coverage.d.ts.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/coverage.js +231 -0
- package/dist/apps/design-system-dashboard/scoring/coverage.js.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/engine.d.ts +27 -0
- package/dist/apps/design-system-dashboard/scoring/engine.d.ts.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/engine.js +93 -0
- package/dist/apps/design-system-dashboard/scoring/engine.js.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/naming-semantics.d.ts +14 -0
- package/dist/apps/design-system-dashboard/scoring/naming-semantics.d.ts.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/naming-semantics.js +309 -0
- package/dist/apps/design-system-dashboard/scoring/naming-semantics.js.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/token-architecture.d.ts +14 -0
- package/dist/apps/design-system-dashboard/scoring/token-architecture.d.ts.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/token-architecture.js +350 -0
- package/dist/apps/design-system-dashboard/scoring/token-architecture.js.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/types.d.ts +89 -0
- package/dist/apps/design-system-dashboard/scoring/types.d.ts.map +1 -0
- package/dist/apps/design-system-dashboard/scoring/types.js +41 -0
- package/dist/apps/design-system-dashboard/scoring/types.js.map +1 -0
- package/dist/apps/design-system-dashboard/server.d.ts +24 -0
- package/dist/apps/design-system-dashboard/server.d.ts.map +1 -0
- package/dist/apps/design-system-dashboard/server.js +160 -0
- package/dist/apps/design-system-dashboard/server.js.map +1 -0
- package/dist/apps/token-browser/server.d.ts +26 -0
- package/dist/apps/token-browser/server.d.ts.map +1 -0
- package/dist/apps/token-browser/server.js +137 -0
- package/dist/apps/token-browser/server.js.map +1 -0
- package/dist/browser/base.d.ts +58 -0
- package/dist/browser/base.d.ts.map +1 -0
- package/dist/browser/base.js +6 -0
- package/dist/browser/base.js.map +1 -0
- package/dist/browser/local.d.ts +87 -0
- package/dist/browser/local.d.ts.map +1 -0
- package/dist/browser/local.js +318 -0
- package/dist/browser/local.js.map +1 -0
- package/dist/core/accessibility-tools.d.ts +21 -0
- package/dist/core/accessibility-tools.d.ts.map +1 -0
- package/dist/core/accessibility-tools.js +307 -0
- package/dist/core/accessibility-tools.js.map +1 -0
- package/dist/core/annotation-tools.d.ts +14 -0
- package/dist/core/annotation-tools.d.ts.map +1 -0
- package/dist/core/annotation-tools.js +231 -0
- package/dist/core/annotation-tools.js.map +1 -0
- package/dist/core/autodocs-tools.d.ts +7 -0
- package/dist/core/autodocs-tools.d.ts.map +1 -0
- package/dist/core/autodocs-tools.js +195 -0
- package/dist/core/autodocs-tools.js.map +1 -0
- package/dist/core/comment-tools.d.ts +11 -0
- package/dist/core/comment-tools.d.ts.map +1 -0
- package/dist/core/comment-tools.js +293 -0
- package/dist/core/comment-tools.js.map +1 -0
- package/dist/core/config.d.ts +17 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +154 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/console-monitor.d.ts +82 -0
- package/dist/core/console-monitor.d.ts.map +1 -0
- package/dist/core/console-monitor.js +428 -0
- package/dist/core/console-monitor.js.map +1 -0
- package/dist/core/deep-component-tools.d.ts +14 -0
- package/dist/core/deep-component-tools.d.ts.map +1 -0
- package/dist/core/deep-component-tools.js +129 -0
- package/dist/core/deep-component-tools.js.map +1 -0
- package/dist/core/design-code-tools.d.ts +116 -0
- package/dist/core/design-code-tools.d.ts.map +1 -0
- package/dist/core/design-code-tools.js +2751 -0
- package/dist/core/design-code-tools.js.map +1 -0
- package/dist/core/design-system-manifest.d.ts +272 -0
- package/dist/core/design-system-manifest.d.ts.map +1 -0
- package/dist/core/design-system-manifest.js +261 -0
- package/dist/core/design-system-manifest.js.map +1 -0
- package/dist/core/design-system-tools.d.ts +67 -0
- package/dist/core/design-system-tools.d.ts.map +1 -0
- package/dist/core/design-system-tools.js +874 -0
- package/dist/core/design-system-tools.js.map +1 -0
- package/dist/core/diagnose-tool.d.ts +33 -0
- package/dist/core/diagnose-tool.d.ts.map +1 -0
- package/dist/core/diagnose-tool.js +97 -0
- package/dist/core/diagnose-tool.js.map +1 -0
- package/dist/core/diff/changelog-formatter.d.ts +35 -0
- package/dist/core/diff/changelog-formatter.d.ts.map +1 -0
- package/dist/core/diff/changelog-formatter.js +276 -0
- package/dist/core/diff/changelog-formatter.js.map +1 -0
- package/dist/core/diff/diff-engine.d.ts +127 -0
- package/dist/core/diff/diff-engine.d.ts.map +1 -0
- package/dist/core/diff/diff-engine.js +335 -0
- package/dist/core/diff/diff-engine.js.map +1 -0
- package/dist/core/diff/property-compare.d.ts +19 -0
- package/dist/core/diff/property-compare.d.ts.map +1 -0
- package/dist/core/diff/property-compare.js +37 -0
- package/dist/core/diff/property-compare.js.map +1 -0
- package/dist/core/diff/version-cache.d.ts +40 -0
- package/dist/core/diff/version-cache.d.ts.map +1 -0
- package/dist/core/diff/version-cache.js +75 -0
- package/dist/core/diff/version-cache.js.map +1 -0
- package/dist/core/enrichment/enrichment-service.d.ts +52 -0
- package/dist/core/enrichment/enrichment-service.d.ts.map +1 -0
- package/dist/core/enrichment/enrichment-service.js +369 -0
- package/dist/core/enrichment/enrichment-service.js.map +1 -0
- package/dist/core/enrichment/index.d.ts +8 -0
- package/dist/core/enrichment/index.d.ts.map +1 -0
- package/dist/core/enrichment/index.js +8 -0
- package/dist/core/enrichment/index.js.map +1 -0
- package/dist/core/enrichment/relationship-mapper.d.ts +106 -0
- package/dist/core/enrichment/relationship-mapper.d.ts.map +1 -0
- package/dist/core/enrichment/relationship-mapper.js +352 -0
- package/dist/core/enrichment/relationship-mapper.js.map +1 -0
- package/dist/core/enrichment/style-resolver.d.ts +80 -0
- package/dist/core/enrichment/style-resolver.d.ts.map +1 -0
- package/dist/core/enrichment/style-resolver.js +327 -0
- package/dist/core/enrichment/style-resolver.js.map +1 -0
- package/dist/core/figjam-tools.d.ts +8 -0
- package/dist/core/figjam-tools.d.ts.map +1 -0
- package/dist/core/figjam-tools.js +548 -0
- package/dist/core/figjam-tools.js.map +1 -0
- package/dist/core/figma-api.d.ts +245 -0
- package/dist/core/figma-api.d.ts.map +1 -0
- package/dist/core/figma-api.js +446 -0
- package/dist/core/figma-api.js.map +1 -0
- package/dist/core/figma-connector.d.ts +180 -0
- package/dist/core/figma-connector.d.ts.map +1 -0
- package/dist/core/figma-connector.js +8 -0
- package/dist/core/figma-connector.js.map +1 -0
- package/dist/core/figma-desktop-connector.d.ts +312 -0
- package/dist/core/figma-desktop-connector.d.ts.map +1 -0
- package/dist/core/figma-desktop-connector.js +1298 -0
- package/dist/core/figma-desktop-connector.js.map +1 -0
- package/dist/core/figma-reconstruction-spec.d.ts +166 -0
- package/dist/core/figma-reconstruction-spec.d.ts.map +1 -0
- package/dist/core/figma-reconstruction-spec.js +403 -0
- package/dist/core/figma-reconstruction-spec.js.map +1 -0
- package/dist/core/figma-style-extractor.d.ts +76 -0
- package/dist/core/figma-style-extractor.d.ts.map +1 -0
- package/dist/core/figma-style-extractor.js +312 -0
- package/dist/core/figma-style-extractor.js.map +1 -0
- package/dist/core/figma-tools.d.ts +22 -0
- package/dist/core/figma-tools.d.ts.map +1 -0
- package/dist/core/figma-tools.js +3187 -0
- package/dist/core/figma-tools.js.map +1 -0
- package/dist/core/identity.d.ts +41 -0
- package/dist/core/identity.d.ts.map +1 -0
- package/dist/core/identity.js +97 -0
- package/dist/core/identity.js.map +1 -0
- package/dist/core/library-tools.d.ts +17 -0
- package/dist/core/library-tools.d.ts.map +1 -0
- package/dist/core/library-tools.js +581 -0
- package/dist/core/library-tools.js.map +1 -0
- package/dist/core/logger.d.ts +22 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +54 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/port-discovery.d.ts +171 -0
- package/dist/core/port-discovery.d.ts.map +1 -0
- package/dist/core/port-discovery.js +563 -0
- package/dist/core/port-discovery.js.map +1 -0
- package/dist/core/resolve-package-root.d.ts +2 -0
- package/dist/core/resolve-package-root.d.ts.map +1 -0
- package/dist/core/resolve-package-root.js +12 -0
- package/dist/core/resolve-package-root.js.map +1 -0
- package/dist/core/slides-tools.d.ts +8 -0
- package/dist/core/slides-tools.d.ts.map +1 -0
- package/dist/core/slides-tools.js +715 -0
- package/dist/core/slides-tools.js.map +1 -0
- package/dist/core/snippet-injector.d.ts +24 -0
- package/dist/core/snippet-injector.d.ts.map +1 -0
- package/dist/core/snippet-injector.js +97 -0
- package/dist/core/snippet-injector.js.map +1 -0
- package/dist/core/tokens/alias-resolver.d.ts +55 -0
- package/dist/core/tokens/alias-resolver.d.ts.map +1 -0
- package/dist/core/tokens/alias-resolver.js +136 -0
- package/dist/core/tokens/alias-resolver.js.map +1 -0
- package/dist/core/tokens/config.d.ts +87 -0
- package/dist/core/tokens/config.d.ts.map +1 -0
- package/dist/core/tokens/config.js +285 -0
- package/dist/core/tokens/config.js.map +1 -0
- package/dist/core/tokens/figma-converter.d.ts +81 -0
- package/dist/core/tokens/figma-converter.d.ts.map +1 -0
- package/dist/core/tokens/figma-converter.js +196 -0
- package/dist/core/tokens/figma-converter.js.map +1 -0
- package/dist/core/tokens/formatters/css-vars.d.ts +24 -0
- package/dist/core/tokens/formatters/css-vars.d.ts.map +1 -0
- package/dist/core/tokens/formatters/css-vars.js +330 -0
- package/dist/core/tokens/formatters/css-vars.js.map +1 -0
- package/dist/core/tokens/formatters/dtcg.d.ts +28 -0
- package/dist/core/tokens/formatters/dtcg.d.ts.map +1 -0
- package/dist/core/tokens/formatters/dtcg.js +301 -0
- package/dist/core/tokens/formatters/dtcg.js.map +1 -0
- package/dist/core/tokens/formatters/index.d.ts +30 -0
- package/dist/core/tokens/formatters/index.d.ts.map +1 -0
- package/dist/core/tokens/formatters/index.js +46 -0
- package/dist/core/tokens/formatters/index.js.map +1 -0
- package/dist/core/tokens/formatters/json.d.ts +37 -0
- package/dist/core/tokens/formatters/json.d.ts.map +1 -0
- package/dist/core/tokens/formatters/json.js +188 -0
- package/dist/core/tokens/formatters/json.js.map +1 -0
- package/dist/core/tokens/formatters/less.d.ts +4 -0
- package/dist/core/tokens/formatters/less.d.ts.map +1 -0
- package/dist/core/tokens/formatters/less.js +5 -0
- package/dist/core/tokens/formatters/less.js.map +1 -0
- package/dist/core/tokens/formatters/scss.d.ts +26 -0
- package/dist/core/tokens/formatters/scss.d.ts.map +1 -0
- package/dist/core/tokens/formatters/scss.js +253 -0
- package/dist/core/tokens/formatters/scss.js.map +1 -0
- package/dist/core/tokens/formatters/stubs.d.ts +9 -0
- package/dist/core/tokens/formatters/stubs.d.ts.map +1 -0
- package/dist/core/tokens/formatters/stubs.js +14 -0
- package/dist/core/tokens/formatters/stubs.js.map +1 -0
- package/dist/core/tokens/formatters/style-dictionary-v3.d.ts +45 -0
- package/dist/core/tokens/formatters/style-dictionary-v3.d.ts.map +1 -0
- package/dist/core/tokens/formatters/style-dictionary-v3.js +208 -0
- package/dist/core/tokens/formatters/style-dictionary-v3.js.map +1 -0
- package/dist/core/tokens/formatters/tailwind-v3.d.ts +37 -0
- package/dist/core/tokens/formatters/tailwind-v3.d.ts.map +1 -0
- package/dist/core/tokens/formatters/tailwind-v3.js +238 -0
- package/dist/core/tokens/formatters/tailwind-v3.js.map +1 -0
- package/dist/core/tokens/formatters/tailwind-v4.d.ts +41 -0
- package/dist/core/tokens/formatters/tailwind-v4.d.ts.map +1 -0
- package/dist/core/tokens/formatters/tailwind-v4.js +331 -0
- package/dist/core/tokens/formatters/tailwind-v4.js.map +1 -0
- package/dist/core/tokens/formatters/tokens-studio.d.ts +44 -0
- package/dist/core/tokens/formatters/tokens-studio.d.ts.map +1 -0
- package/dist/core/tokens/formatters/tokens-studio.js +251 -0
- package/dist/core/tokens/formatters/tokens-studio.js.map +1 -0
- package/dist/core/tokens/formatters/ts-module.d.ts +35 -0
- package/dist/core/tokens/formatters/ts-module.d.ts.map +1 -0
- package/dist/core/tokens/formatters/ts-module.js +199 -0
- package/dist/core/tokens/formatters/ts-module.js.map +1 -0
- package/dist/core/tokens/index.d.ts +17 -0
- package/dist/core/tokens/index.d.ts.map +1 -0
- package/dist/core/tokens/index.js +16 -0
- package/dist/core/tokens/index.js.map +1 -0
- package/dist/core/tokens/parsers/css-vars.d.ts +3 -0
- package/dist/core/tokens/parsers/css-vars.d.ts.map +1 -0
- package/dist/core/tokens/parsers/css-vars.js +5 -0
- package/dist/core/tokens/parsers/css-vars.js.map +1 -0
- package/dist/core/tokens/parsers/dtcg.d.ts +21 -0
- package/dist/core/tokens/parsers/dtcg.d.ts.map +1 -0
- package/dist/core/tokens/parsers/dtcg.js +254 -0
- package/dist/core/tokens/parsers/dtcg.js.map +1 -0
- package/dist/core/tokens/parsers/index.d.ts +37 -0
- package/dist/core/tokens/parsers/index.d.ts.map +1 -0
- package/dist/core/tokens/parsers/index.js +139 -0
- package/dist/core/tokens/parsers/index.js.map +1 -0
- package/dist/core/tokens/parsers/json.d.ts +4 -0
- package/dist/core/tokens/parsers/json.d.ts.map +1 -0
- package/dist/core/tokens/parsers/json.js +8 -0
- package/dist/core/tokens/parsers/json.js.map +1 -0
- package/dist/core/tokens/parsers/scss.d.ts +3 -0
- package/dist/core/tokens/parsers/scss.d.ts.map +1 -0
- package/dist/core/tokens/parsers/scss.js +5 -0
- package/dist/core/tokens/parsers/scss.js.map +1 -0
- package/dist/core/tokens/parsers/stubs.d.ts +15 -0
- package/dist/core/tokens/parsers/stubs.d.ts.map +1 -0
- package/dist/core/tokens/parsers/stubs.js +21 -0
- package/dist/core/tokens/parsers/stubs.js.map +1 -0
- package/dist/core/tokens/parsers/style-dictionary-v3.d.ts +3 -0
- package/dist/core/tokens/parsers/style-dictionary-v3.d.ts.map +1 -0
- package/dist/core/tokens/parsers/style-dictionary-v3.js +5 -0
- package/dist/core/tokens/parsers/style-dictionary-v3.js.map +1 -0
- package/dist/core/tokens/parsers/tailwind-v3.d.ts +3 -0
- package/dist/core/tokens/parsers/tailwind-v3.d.ts.map +1 -0
- package/dist/core/tokens/parsers/tailwind-v3.js +5 -0
- package/dist/core/tokens/parsers/tailwind-v3.js.map +1 -0
- package/dist/core/tokens/parsers/tailwind-v4.d.ts +3 -0
- package/dist/core/tokens/parsers/tailwind-v4.d.ts.map +1 -0
- package/dist/core/tokens/parsers/tailwind-v4.js +5 -0
- package/dist/core/tokens/parsers/tailwind-v4.js.map +1 -0
- package/dist/core/tokens/parsers/tokens-studio.d.ts +3 -0
- package/dist/core/tokens/parsers/tokens-studio.d.ts.map +1 -0
- package/dist/core/tokens/parsers/tokens-studio.js +5 -0
- package/dist/core/tokens/parsers/tokens-studio.js.map +1 -0
- package/dist/core/tokens/schemas.d.ts +31 -0
- package/dist/core/tokens/schemas.d.ts.map +1 -0
- package/dist/core/tokens/schemas.js +149 -0
- package/dist/core/tokens/schemas.js.map +1 -0
- package/dist/core/tokens/transforms/color.d.ts +9 -0
- package/dist/core/tokens/transforms/color.d.ts.map +1 -0
- package/dist/core/tokens/transforms/color.js +13 -0
- package/dist/core/tokens/transforms/color.js.map +1 -0
- package/dist/core/tokens/transforms/index.d.ts +36 -0
- package/dist/core/tokens/transforms/index.d.ts.map +1 -0
- package/dist/core/tokens/transforms/index.js +30 -0
- package/dist/core/tokens/transforms/index.js.map +1 -0
- package/dist/core/tokens/transforms/size.d.ts +7 -0
- package/dist/core/tokens/transforms/size.d.ts.map +1 -0
- package/dist/core/tokens/transforms/size.js +8 -0
- package/dist/core/tokens/transforms/size.js.map +1 -0
- package/dist/core/tokens/types.d.ts +228 -0
- package/dist/core/tokens/types.d.ts.map +1 -0
- package/dist/core/tokens/types.js +19 -0
- package/dist/core/tokens/types.js.map +1 -0
- package/dist/core/tokens-tools.d.ts +42 -0
- package/dist/core/tokens-tools.d.ts.map +1 -0
- package/dist/core/tokens-tools.js +860 -0
- package/dist/core/tokens-tools.js.map +1 -0
- package/dist/core/types/design-code.d.ts +271 -0
- package/dist/core/types/design-code.d.ts.map +1 -0
- package/dist/core/types/design-code.js +5 -0
- package/dist/core/types/design-code.js.map +1 -0
- package/dist/core/types/enriched.d.ts +213 -0
- package/dist/core/types/enriched.d.ts.map +1 -0
- package/dist/core/types/enriched.js +6 -0
- package/dist/core/types/enriched.js.map +1 -0
- package/dist/core/types/index.d.ts +104 -0
- package/dist/core/types/index.d.ts.map +1 -0
- package/dist/core/types/index.js +5 -0
- package/dist/core/types/index.js.map +1 -0
- package/dist/core/variable-resolver.d.ts +45 -0
- package/dist/core/variable-resolver.d.ts.map +1 -0
- package/dist/core/variable-resolver.js +86 -0
- package/dist/core/variable-resolver.js.map +1 -0
- package/dist/core/version-tools.d.ts +59 -0
- package/dist/core/version-tools.d.ts.map +1 -0
- package/dist/core/version-tools.js +1159 -0
- package/dist/core/version-tools.js.map +1 -0
- package/dist/core/websocket-connector.d.ts +187 -0
- package/dist/core/websocket-connector.d.ts.map +1 -0
- package/dist/core/websocket-connector.js +378 -0
- package/dist/core/websocket-connector.js.map +1 -0
- package/dist/core/websocket-server.js +866 -0
- package/dist/core/websocket-server.js.map +1 -0
- package/dist/core/write-tools.d.ts +7 -0
- package/dist/core/write-tools.d.ts.map +1 -0
- package/dist/core/write-tools.js +2172 -0
- package/dist/core/write-tools.js.map +1 -0
- package/dist/local.d.ts +95 -0
- package/dist/local.d.ts.map +1 -0
- package/dist/local.js +3036 -0
- package/dist/local.js.map +1 -0
- package/dist/vendor/obra-autodocs/autodocs-body.generated.d.ts +2 -0
- package/dist/vendor/obra-autodocs/autodocs-body.generated.d.ts.map +1 -0
- package/dist/vendor/obra-autodocs/autodocs-body.generated.js +6 -0
- package/dist/vendor/obra-autodocs/autodocs-body.generated.js.map +1 -0
- package/figma-desktop-bridge/README.md +365 -0
- package/figma-desktop-bridge/code.js +6504 -0
- package/figma-desktop-bridge/icon.png +0 -0
- package/figma-desktop-bridge/manifest.json +67 -0
- package/figma-desktop-bridge/ui.html +2441 -0
- package/package.json +98 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tailwind v4 `@theme` block formatter.
|
|
3
|
+
*
|
|
4
|
+
* Tailwind v4 introduced CSS-first configuration: instead of a JS
|
|
5
|
+
* `tailwind.config.js`, you write tokens directly into your CSS with an
|
|
6
|
+
* `@theme inline { ... }` block. Tailwind processes that block to generate
|
|
7
|
+
* utility classes (`bg-primary`, `text-foreground`, etc.) at build time.
|
|
8
|
+
*
|
|
9
|
+
* Output shape:
|
|
10
|
+
*
|
|
11
|
+
* @theme inline {
|
|
12
|
+
* --color-primary: #4085F2;
|
|
13
|
+
* --spacing-md: 16px;
|
|
14
|
+
* --font-family-sans: "Inter", sans-serif;
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* .dark {
|
|
18
|
+
* --color-primary: #5599FF;
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* Token-to-Tailwind-namespace mapping follows the canonical Tailwind v4
|
|
22
|
+
* convention (see https://tailwindcss.com/docs/theme):
|
|
23
|
+
*
|
|
24
|
+
* color/* → --color-* (maps to bg-*, text-*, border-*, etc.)
|
|
25
|
+
* spacing/* → --spacing-*
|
|
26
|
+
* radius/* → --radius-* (maps to rounded-*)
|
|
27
|
+
* font/* → --font-* (font-family namespace)
|
|
28
|
+
* text/* → --text-* (font-size namespace)
|
|
29
|
+
* font-weight/* → --font-weight-*
|
|
30
|
+
* tracking/* → --tracking-*
|
|
31
|
+
* leading/* → --leading-*
|
|
32
|
+
* shadow/* → --shadow-*
|
|
33
|
+
*
|
|
34
|
+
* Tokens that don't fit a known Tailwind namespace get emitted with their
|
|
35
|
+
* path verbatim (with prefix if configured). They're still valid CSS vars
|
|
36
|
+
* — they just don't generate Tailwind utility classes.
|
|
37
|
+
*/
|
|
38
|
+
export function formatTailwindV4(doc, opts) {
|
|
39
|
+
const warnings = [];
|
|
40
|
+
const files = [];
|
|
41
|
+
const splitByMode = opts.target.splitByMode ?? false;
|
|
42
|
+
const splitByCollection = opts.target.splitByCollection ?? false;
|
|
43
|
+
const prefix = opts.target.prefix ?? "";
|
|
44
|
+
if (splitByMode && splitByCollection) {
|
|
45
|
+
for (const set of doc.sets) {
|
|
46
|
+
for (const mode of set.modes) {
|
|
47
|
+
files.push({
|
|
48
|
+
path: filenameFor(opts, set, mode),
|
|
49
|
+
content: renderTailwindFile(doc.sets.filter((s) => s.name === set.name), [mode], prefix, warnings),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else if (splitByMode) {
|
|
55
|
+
const allModes = new Set();
|
|
56
|
+
for (const set of doc.sets)
|
|
57
|
+
for (const m of set.modes)
|
|
58
|
+
allModes.add(m);
|
|
59
|
+
for (const mode of allModes) {
|
|
60
|
+
files.push({
|
|
61
|
+
path: filenameFor(opts, undefined, mode),
|
|
62
|
+
content: renderTailwindFile(doc.sets, [mode], prefix, warnings),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else if (splitByCollection) {
|
|
67
|
+
for (const set of doc.sets) {
|
|
68
|
+
files.push({
|
|
69
|
+
path: filenameFor(opts, set),
|
|
70
|
+
content: renderTailwindFile([set], set.modes, prefix, warnings),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Single file with everything.
|
|
76
|
+
const allModes = new Set();
|
|
77
|
+
for (const set of doc.sets)
|
|
78
|
+
for (const m of set.modes)
|
|
79
|
+
allModes.add(m);
|
|
80
|
+
files.push({
|
|
81
|
+
path: filenameFor(opts),
|
|
82
|
+
content: renderTailwindFile(doc.sets, [...allModes], prefix, warnings),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return { files, warnings };
|
|
86
|
+
}
|
|
87
|
+
function filenameFor(opts, set, mode) {
|
|
88
|
+
if (opts.target.filename)
|
|
89
|
+
return opts.target.filename;
|
|
90
|
+
const parts = [];
|
|
91
|
+
if (set)
|
|
92
|
+
parts.push(slugify(set.name));
|
|
93
|
+
if (mode)
|
|
94
|
+
parts.push(slugify(mode));
|
|
95
|
+
if (parts.length === 0)
|
|
96
|
+
parts.push("tailwind.theme");
|
|
97
|
+
return `${parts.join(".")}.css`;
|
|
98
|
+
}
|
|
99
|
+
function slugify(s) {
|
|
100
|
+
return s
|
|
101
|
+
.trim()
|
|
102
|
+
.toLowerCase()
|
|
103
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
104
|
+
.replace(/^-+|-+$/g, "");
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Render a Tailwind v4 CSS file. The "primary" mode (first in the list)
|
|
108
|
+
* goes into `@theme inline { ... }` — this is what Tailwind reads to
|
|
109
|
+
* generate utility classes. Additional modes go under standard CSS
|
|
110
|
+
* selectors (`.dark`, `[data-theme="..."]`) so the user can swap modes
|
|
111
|
+
* at runtime.
|
|
112
|
+
*/
|
|
113
|
+
function renderTailwindFile(sets, modes, prefix, warnings) {
|
|
114
|
+
const lines = [];
|
|
115
|
+
lines.push("/* Generated by figma-console-mcp — do not edit by hand */");
|
|
116
|
+
lines.push("");
|
|
117
|
+
// Decide which mode is the "primary" (lives inside @theme).
|
|
118
|
+
const primaryMode = modes.find((m) => /^(default|light|value)$/i.test(m)) ?? modes[0];
|
|
119
|
+
// @theme inline { ... } block for the primary mode.
|
|
120
|
+
lines.push("@theme inline {");
|
|
121
|
+
for (const set of sets) {
|
|
122
|
+
if (!set.modes.includes(primaryMode))
|
|
123
|
+
continue;
|
|
124
|
+
for (const token of set.tokens) {
|
|
125
|
+
const value = token.values[primaryMode];
|
|
126
|
+
if (!value)
|
|
127
|
+
continue;
|
|
128
|
+
emitTailwindTokenLines(token, value, prefix, lines, warnings);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
lines.push("}");
|
|
132
|
+
lines.push("");
|
|
133
|
+
// Mode variants under standard CSS selectors.
|
|
134
|
+
for (const mode of modes) {
|
|
135
|
+
if (mode === primaryMode)
|
|
136
|
+
continue;
|
|
137
|
+
lines.push(`${selectorFor(mode)} {`);
|
|
138
|
+
for (const set of sets) {
|
|
139
|
+
if (!set.modes.includes(mode))
|
|
140
|
+
continue;
|
|
141
|
+
for (const token of set.tokens) {
|
|
142
|
+
const value = token.values[mode];
|
|
143
|
+
if (!value)
|
|
144
|
+
continue;
|
|
145
|
+
emitTailwindTokenLines(token, value, prefix, lines, warnings);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
lines.push("}");
|
|
149
|
+
lines.push("");
|
|
150
|
+
}
|
|
151
|
+
return lines.join("\n");
|
|
152
|
+
}
|
|
153
|
+
function selectorFor(mode) {
|
|
154
|
+
const lower = mode.toLowerCase();
|
|
155
|
+
if (lower === "dark")
|
|
156
|
+
return ".dark";
|
|
157
|
+
return `[data-theme="${slugify(mode)}"]`;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Emit one or more CSS custom property declarations for a token, using
|
|
161
|
+
* Tailwind v4's namespace conventions where possible.
|
|
162
|
+
*/
|
|
163
|
+
function emitTailwindTokenLines(token, value, prefix, out, warnings) {
|
|
164
|
+
const cssName = `--${prefix}${pathToTailwindName(token.path, token.type)}`;
|
|
165
|
+
if (value.reference) {
|
|
166
|
+
// Cross-library alias: skip with a comment.
|
|
167
|
+
const bareRef = value.reference.replace(/^\{|\}$/g, "");
|
|
168
|
+
const libMatch = bareRef.match(/^__library:(.+)$/);
|
|
169
|
+
if (libMatch || bareRef === "unknown") {
|
|
170
|
+
const originalId = libMatch ? libMatch[1] : "unknown";
|
|
171
|
+
warnings.push(`Skipped ${token.path.join(".")} in Tailwind v4 — references cross-library variable ${originalId}.`);
|
|
172
|
+
out.push(` /* ${cssName}: skipped — cross-library alias to ${originalId} */`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
// Local alias → var() reference using the same namespace mapping.
|
|
176
|
+
const refPath = bareRef.split(".");
|
|
177
|
+
const targetName = pathToTailwindName(refPath, token.type);
|
|
178
|
+
out.push(` ${cssName}: var(--${prefix}${targetName});`);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (value.literal === undefined || value.literal === null) {
|
|
182
|
+
warnings.push(`Token ${token.path.join(".")} has no value — emitting nothing.`);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// Composite tokens: typography expands, shadow renders as CSS string.
|
|
186
|
+
if (token.type === "typography" && typeof value.literal === "object") {
|
|
187
|
+
const t = value.literal;
|
|
188
|
+
for (const subField of ["fontFamily", "fontSize", "fontWeight", "lineHeight", "letterSpacing"]) {
|
|
189
|
+
if (t[subField] !== undefined) {
|
|
190
|
+
out.push(` ${cssName}-${kebab(subField)}: ${formatValue(t[subField], token.type)};`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (token.type === "shadow" && typeof value.literal === "object") {
|
|
196
|
+
const css = renderShadow(value.literal);
|
|
197
|
+
if (css)
|
|
198
|
+
out.push(` ${cssName}: ${css};`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
out.push(` ${cssName}: ${formatValue(value.literal, token.type)};`);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Map a token path to a Tailwind v4 CSS custom property name.
|
|
205
|
+
*
|
|
206
|
+
* Strategy:
|
|
207
|
+
* 1. If the path's leading segment matches a Tailwind namespace
|
|
208
|
+
* (color, spacing, radius, font, text, etc.), emit it as-is — that
|
|
209
|
+
* tells Tailwind to generate the corresponding utility class family.
|
|
210
|
+
* 2. Otherwise, prepend our type-based namespace heuristically.
|
|
211
|
+
* 3. Always slugify each segment for valid CSS identifiers.
|
|
212
|
+
*
|
|
213
|
+
* Examples:
|
|
214
|
+
* ["color", "primary"] → "color-primary" (bg-primary works)
|
|
215
|
+
* ["spacing", "md"] → "spacing-md" (p-md works)
|
|
216
|
+
* ["radius", "lg"] → "radius-lg" (rounded-lg works)
|
|
217
|
+
* ["text", "base", "font-size"] → "text-base-font-size"
|
|
218
|
+
* ["semantic", "bg"] (color type) → "color-semantic-bg" (heuristic prepend)
|
|
219
|
+
*/
|
|
220
|
+
function pathToTailwindName(path, type) {
|
|
221
|
+
// Tailwind v4's known namespaces (https://tailwindcss.com/docs/theme).
|
|
222
|
+
const KNOWN = new Set([
|
|
223
|
+
"color",
|
|
224
|
+
"colors",
|
|
225
|
+
"spacing",
|
|
226
|
+
"radius",
|
|
227
|
+
"rounded",
|
|
228
|
+
"shadow",
|
|
229
|
+
"font",
|
|
230
|
+
"text",
|
|
231
|
+
"font-weight",
|
|
232
|
+
"tracking",
|
|
233
|
+
"leading",
|
|
234
|
+
"blur",
|
|
235
|
+
"ease",
|
|
236
|
+
"animate",
|
|
237
|
+
"breakpoint",
|
|
238
|
+
"container",
|
|
239
|
+
"aspect",
|
|
240
|
+
]);
|
|
241
|
+
// Aliases that normalize to a canonical namespace.
|
|
242
|
+
const NORMALIZE = {
|
|
243
|
+
colors: "color",
|
|
244
|
+
rounded: "radius",
|
|
245
|
+
};
|
|
246
|
+
const slug = path.map(slugify);
|
|
247
|
+
if (slug.length === 0)
|
|
248
|
+
return "token";
|
|
249
|
+
// First-segment match: easy case, normalize plural → singular and emit.
|
|
250
|
+
if (KNOWN.has(slug[0])) {
|
|
251
|
+
const head = NORMALIZE[slug[0]] ?? slug[0];
|
|
252
|
+
return [head, ...slug.slice(1)].join("-");
|
|
253
|
+
}
|
|
254
|
+
// Determine the target Tailwind namespace from token type.
|
|
255
|
+
const ns = type === "color"
|
|
256
|
+
? "color"
|
|
257
|
+
: type === "dimension" || type === "number"
|
|
258
|
+
? "spacing"
|
|
259
|
+
: type === "fontFamily"
|
|
260
|
+
? "font"
|
|
261
|
+
: type === "fontWeight"
|
|
262
|
+
? "font-weight"
|
|
263
|
+
: null;
|
|
264
|
+
if (!ns)
|
|
265
|
+
return slug.join("-");
|
|
266
|
+
// Dedup: if the path already contains the target namespace (e.g. a path
|
|
267
|
+
// like `theme.color.header.background` for a color token would otherwise
|
|
268
|
+
// produce `color-theme-color-header-background`), strip the duplicate
|
|
269
|
+
// segment so the result reads cleanly. Match both the canonical name
|
|
270
|
+
// and any alias that normalizes to it.
|
|
271
|
+
const dupAliases = new Set([ns, ...Object.entries(NORMALIZE)
|
|
272
|
+
.filter(([, target]) => target === ns)
|
|
273
|
+
.map(([alias]) => alias)]);
|
|
274
|
+
const dedupedTail = slug.filter((s) => !dupAliases.has(s));
|
|
275
|
+
return [ns, ...dedupedTail].join("-");
|
|
276
|
+
}
|
|
277
|
+
function kebab(s) {
|
|
278
|
+
return s.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
279
|
+
}
|
|
280
|
+
function formatValue(value, type) {
|
|
281
|
+
if (typeof value === "number") {
|
|
282
|
+
if (type === "dimension")
|
|
283
|
+
return `${value}px`;
|
|
284
|
+
return String(value);
|
|
285
|
+
}
|
|
286
|
+
if (typeof value === "string") {
|
|
287
|
+
if (type === "color")
|
|
288
|
+
return value;
|
|
289
|
+
if (type === "fontFamily" || type === "string") {
|
|
290
|
+
return needsQuoting(value) ? JSON.stringify(value) : value;
|
|
291
|
+
}
|
|
292
|
+
return value;
|
|
293
|
+
}
|
|
294
|
+
if (typeof value === "boolean")
|
|
295
|
+
return String(value);
|
|
296
|
+
return JSON.stringify(value);
|
|
297
|
+
}
|
|
298
|
+
function needsQuoting(s) {
|
|
299
|
+
if (/^["']/.test(s))
|
|
300
|
+
return false;
|
|
301
|
+
if (/^[\d.]+([a-z%]+)?$/.test(s))
|
|
302
|
+
return false;
|
|
303
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(s))
|
|
304
|
+
return false;
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
function renderShadow(shadow) {
|
|
308
|
+
if (Array.isArray(shadow)) {
|
|
309
|
+
return shadow.map(renderShadow).filter(Boolean).join(", ");
|
|
310
|
+
}
|
|
311
|
+
if (!shadow || typeof shadow !== "object")
|
|
312
|
+
return null;
|
|
313
|
+
const s = shadow;
|
|
314
|
+
const inset = s.inset ? "inset " : "";
|
|
315
|
+
const x = withPx(s.offsetX);
|
|
316
|
+
const y = withPx(s.offsetY);
|
|
317
|
+
const blur = withPx(s.blur);
|
|
318
|
+
const spread = s.spread !== undefined ? ` ${withPx(s.spread)}` : "";
|
|
319
|
+
const color = s.color;
|
|
320
|
+
if (!x || !y || !blur || typeof color !== "string")
|
|
321
|
+
return null;
|
|
322
|
+
return `${inset}${x} ${y} ${blur}${spread} ${color}`;
|
|
323
|
+
}
|
|
324
|
+
function withPx(v) {
|
|
325
|
+
if (typeof v === "number")
|
|
326
|
+
return `${v}px`;
|
|
327
|
+
if (typeof v === "string")
|
|
328
|
+
return v;
|
|
329
|
+
return "";
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=tailwind-v4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tailwind-v4.js","sourceRoot":"","sources":["../../../../src/core/tokens/formatters/tailwind-v4.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tokens Studio for Figma JSON formatter.
|
|
3
|
+
*
|
|
4
|
+
* Tokens Studio uses a multi-file layout:
|
|
5
|
+
*
|
|
6
|
+
* $themes.json — array of theme definitions with selectedTokenSets
|
|
7
|
+
* $metadata.json — list of token set names + tokenSetOrder
|
|
8
|
+
* primitives.json — one file per token set
|
|
9
|
+
* semantic.json
|
|
10
|
+
* theme/light.json
|
|
11
|
+
* theme/dark.json
|
|
12
|
+
*
|
|
13
|
+
* Each per-set file holds tokens with the Tokens Studio shape:
|
|
14
|
+
*
|
|
15
|
+
* {
|
|
16
|
+
* "color": {
|
|
17
|
+
* "primary": {
|
|
18
|
+
* "value": "#4085F2",
|
|
19
|
+
* "type": "color",
|
|
20
|
+
* "description": "Primary brand color"
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* Tokens Studio uses bare `value` / `type` (no `$` prefix — same as
|
|
26
|
+
* Style Dictionary v3, which the plugin's format is based on). Aliases
|
|
27
|
+
* use `{path.to.token}` syntax.
|
|
28
|
+
*
|
|
29
|
+
* `$themes.json` carries the Figma collection/mode bindings that make
|
|
30
|
+
* Tokens Studio's "send to Figma" feature work — preserved here for
|
|
31
|
+
* round-trip with Tokens Studio plugin users (notably Altitude).
|
|
32
|
+
*
|
|
33
|
+
* Output strategy:
|
|
34
|
+
* - One file per TokenSet, named after the set (slugified).
|
|
35
|
+
* - Multi-mode sets emit one file per (set, mode) pair (Tokens Studio
|
|
36
|
+
* convention).
|
|
37
|
+
* - `$metadata.json` enumerates the token set names in order.
|
|
38
|
+
* - `$themes.json` builds a theme entry per mode with selectedTokenSets
|
|
39
|
+
* and the figma-console-mcp metadata stamped onto it.
|
|
40
|
+
*/
|
|
41
|
+
import type { TokenDocument } from "../types.js";
|
|
42
|
+
import type { FormatOptions, FormatResult } from "./index.js";
|
|
43
|
+
export declare function formatTokensStudio(doc: TokenDocument, opts: FormatOptions): FormatResult;
|
|
44
|
+
//# sourceMappingURL=tokens-studio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens-studio.d.ts","sourceRoot":"","sources":["../../../../src/core/tokens/formatters/tokens-studio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAS,aAAa,EAAwB,MAAM,aAAa,CAAC;AAE9E,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,aAAa,GAClB,YAAY,CAwCd"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tokens Studio for Figma JSON formatter.
|
|
3
|
+
*
|
|
4
|
+
* Tokens Studio uses a multi-file layout:
|
|
5
|
+
*
|
|
6
|
+
* $themes.json — array of theme definitions with selectedTokenSets
|
|
7
|
+
* $metadata.json — list of token set names + tokenSetOrder
|
|
8
|
+
* primitives.json — one file per token set
|
|
9
|
+
* semantic.json
|
|
10
|
+
* theme/light.json
|
|
11
|
+
* theme/dark.json
|
|
12
|
+
*
|
|
13
|
+
* Each per-set file holds tokens with the Tokens Studio shape:
|
|
14
|
+
*
|
|
15
|
+
* {
|
|
16
|
+
* "color": {
|
|
17
|
+
* "primary": {
|
|
18
|
+
* "value": "#4085F2",
|
|
19
|
+
* "type": "color",
|
|
20
|
+
* "description": "Primary brand color"
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* Tokens Studio uses bare `value` / `type` (no `$` prefix — same as
|
|
26
|
+
* Style Dictionary v3, which the plugin's format is based on). Aliases
|
|
27
|
+
* use `{path.to.token}` syntax.
|
|
28
|
+
*
|
|
29
|
+
* `$themes.json` carries the Figma collection/mode bindings that make
|
|
30
|
+
* Tokens Studio's "send to Figma" feature work — preserved here for
|
|
31
|
+
* round-trip with Tokens Studio plugin users (notably Altitude).
|
|
32
|
+
*
|
|
33
|
+
* Output strategy:
|
|
34
|
+
* - One file per TokenSet, named after the set (slugified).
|
|
35
|
+
* - Multi-mode sets emit one file per (set, mode) pair (Tokens Studio
|
|
36
|
+
* convention).
|
|
37
|
+
* - `$metadata.json` enumerates the token set names in order.
|
|
38
|
+
* - `$themes.json` builds a theme entry per mode with selectedTokenSets
|
|
39
|
+
* and the figma-console-mcp metadata stamped onto it.
|
|
40
|
+
*/
|
|
41
|
+
import { FIGMA_MCP_EXTENSION_KEY } from "../types.js";
|
|
42
|
+
export function formatTokensStudio(doc, opts) {
|
|
43
|
+
const warnings = [];
|
|
44
|
+
const files = [];
|
|
45
|
+
// Track which (setName, mode) → filename pairs exist so $metadata + $themes
|
|
46
|
+
// can reference them.
|
|
47
|
+
const setNamesByMode = [];
|
|
48
|
+
// 1. Per-set per-mode token files.
|
|
49
|
+
for (const set of doc.sets) {
|
|
50
|
+
for (const mode of set.modes) {
|
|
51
|
+
const fileSetName = set.modes.length > 1 ? `${slugify(set.name)}/${slugify(mode)}` : slugify(set.name);
|
|
52
|
+
const filename = `${fileSetName}.json`;
|
|
53
|
+
setNamesByMode.push({ setName: fileSetName, mode, filename });
|
|
54
|
+
files.push({
|
|
55
|
+
path: filename,
|
|
56
|
+
content: renderSetFile(set, mode, warnings),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// 2. $metadata.json — ordered list of token sets.
|
|
61
|
+
const tokenSetOrder = setNamesByMode.map((e) => e.setName);
|
|
62
|
+
files.push({
|
|
63
|
+
path: "$metadata.json",
|
|
64
|
+
content: JSON.stringify({ tokenSetOrder }, null, 2) + "\n",
|
|
65
|
+
});
|
|
66
|
+
// 3. $themes.json — one theme entry per mode, with figma-console-mcp
|
|
67
|
+
// metadata so the Tokens Studio plugin's Figma sync features know
|
|
68
|
+
// which Figma collection/mode each theme maps to.
|
|
69
|
+
const themes = buildThemes(doc, setNamesByMode);
|
|
70
|
+
files.push({
|
|
71
|
+
path: "$themes.json",
|
|
72
|
+
content: JSON.stringify(themes, null, 2) + "\n",
|
|
73
|
+
});
|
|
74
|
+
return { files, warnings };
|
|
75
|
+
}
|
|
76
|
+
function slugify(s) {
|
|
77
|
+
return s
|
|
78
|
+
.trim()
|
|
79
|
+
.toLowerCase()
|
|
80
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
81
|
+
.replace(/^-+|-+$/g, "");
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Render a single set's tokens for a specific mode in Tokens Studio's
|
|
85
|
+
* bare-key JSON format.
|
|
86
|
+
*/
|
|
87
|
+
function renderSetFile(set, mode, warnings) {
|
|
88
|
+
const tree = {};
|
|
89
|
+
for (const token of set.tokens) {
|
|
90
|
+
const value = token.values[mode];
|
|
91
|
+
if (!value)
|
|
92
|
+
continue;
|
|
93
|
+
const tsValue = tsValueFor(value, token, warnings);
|
|
94
|
+
if (tsValue === undefined)
|
|
95
|
+
continue;
|
|
96
|
+
// Walk path creating nested groups.
|
|
97
|
+
let cursor = tree;
|
|
98
|
+
for (let i = 0; i < token.path.length - 1; i++) {
|
|
99
|
+
const segment = token.path[i];
|
|
100
|
+
if (!cursor[segment] || typeof cursor[segment] !== "object") {
|
|
101
|
+
cursor[segment] = {};
|
|
102
|
+
}
|
|
103
|
+
cursor = cursor[segment];
|
|
104
|
+
}
|
|
105
|
+
const leafKey = token.path[token.path.length - 1];
|
|
106
|
+
const leaf = {
|
|
107
|
+
value: tsValue,
|
|
108
|
+
type: tsTypeFor(token),
|
|
109
|
+
};
|
|
110
|
+
if (token.description)
|
|
111
|
+
leaf.description = token.description;
|
|
112
|
+
cursor[leafKey] = leaf;
|
|
113
|
+
}
|
|
114
|
+
return JSON.stringify(sortKeys(tree), null, 2) + "\n";
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Build the $themes.json structure. One theme entry per (set, mode) tuple.
|
|
118
|
+
* For multi-mode sets, the theme name combines set + mode.
|
|
119
|
+
*/
|
|
120
|
+
function buildThemes(doc, setNamesByMode) {
|
|
121
|
+
const themes = [];
|
|
122
|
+
// Group by mode so each mode gets one theme entry pulling in the
|
|
123
|
+
// appropriate set files.
|
|
124
|
+
const allModes = new Set();
|
|
125
|
+
for (const e of setNamesByMode)
|
|
126
|
+
allModes.add(e.mode);
|
|
127
|
+
for (const mode of allModes) {
|
|
128
|
+
const selectedTokenSets = {};
|
|
129
|
+
for (const e of setNamesByMode) {
|
|
130
|
+
if (e.mode === mode) {
|
|
131
|
+
selectedTokenSets[e.setName] = "enabled";
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// Other-mode sets are disabled in this theme (Tokens Studio
|
|
135
|
+
// convention: only one mode of each set is "enabled" per theme).
|
|
136
|
+
selectedTokenSets[e.setName] = "source";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Find the Figma collection + mode IDs for this mode (preserved
|
|
140
|
+
// from the export converter's $extensions metadata).
|
|
141
|
+
const figmaCollectionId = findCollectionIdForMode(doc, mode);
|
|
142
|
+
const figmaModeId = findModeId(doc, mode);
|
|
143
|
+
const theme = {
|
|
144
|
+
id: `${slugify(mode)}-${Math.random().toString(36).slice(2, 10)}`,
|
|
145
|
+
name: mode,
|
|
146
|
+
selectedTokenSets,
|
|
147
|
+
};
|
|
148
|
+
// Stash Figma metadata for round-trip with Tokens Studio plugin.
|
|
149
|
+
if (figmaCollectionId)
|
|
150
|
+
theme.$figmaCollectionId = figmaCollectionId;
|
|
151
|
+
if (figmaModeId)
|
|
152
|
+
theme.$figmaModeId = figmaModeId;
|
|
153
|
+
// Also stash our own extension namespace for tools that read it.
|
|
154
|
+
if (figmaCollectionId || figmaModeId) {
|
|
155
|
+
theme.$extensions = {
|
|
156
|
+
[FIGMA_MCP_EXTENSION_KEY]: {
|
|
157
|
+
...(figmaCollectionId ? { figmaCollectionId } : {}),
|
|
158
|
+
...(figmaModeId ? { figmaModeId } : {}),
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
themes.push(theme);
|
|
163
|
+
}
|
|
164
|
+
return themes;
|
|
165
|
+
}
|
|
166
|
+
function findCollectionIdForMode(doc, _mode) {
|
|
167
|
+
// The mode-to-collection mapping requires knowing which set the mode
|
|
168
|
+
// belongs to. For simplicity, return the first collection ID we find;
|
|
169
|
+
// multi-collection support requires per-set theme entries which the
|
|
170
|
+
// Tokens Studio plugin does support.
|
|
171
|
+
for (const set of doc.sets) {
|
|
172
|
+
if (set.meta?.figmaCollectionId)
|
|
173
|
+
return set.meta.figmaCollectionId;
|
|
174
|
+
}
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
function findModeId(_doc, _mode) {
|
|
178
|
+
// We don't carry Figma's modeId through the internal model in this
|
|
179
|
+
// version — it's computed lazily during apply via the
|
|
180
|
+
// (collectionId, modeName) lookup map. Future enhancement: stash the
|
|
181
|
+
// modeId in TokenSet.meta during export so it round-trips through
|
|
182
|
+
// Tokens Studio.
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Map DTCG types to Tokens Studio's type names. Tokens Studio uses SD-style
|
|
187
|
+
* type names with some additions (e.g. "sizing", "borderRadius",
|
|
188
|
+
* "boxShadow", "typography", "opacity", "fontFamilies", "fontWeights").
|
|
189
|
+
*/
|
|
190
|
+
function tsTypeFor(token) {
|
|
191
|
+
if (token.type === "color")
|
|
192
|
+
return "color";
|
|
193
|
+
if (token.type === "fontFamily")
|
|
194
|
+
return "fontFamilies";
|
|
195
|
+
if (token.type === "fontWeight")
|
|
196
|
+
return "fontWeights";
|
|
197
|
+
if (token.type === "typography")
|
|
198
|
+
return "typography";
|
|
199
|
+
if (token.type === "shadow")
|
|
200
|
+
return "boxShadow";
|
|
201
|
+
if (token.type === "duration")
|
|
202
|
+
return "time";
|
|
203
|
+
if (token.type === "dimension") {
|
|
204
|
+
const lower = token.path[0]?.toLowerCase() ?? "";
|
|
205
|
+
if (lower.includes("border") || lower.includes("radius"))
|
|
206
|
+
return "borderRadius";
|
|
207
|
+
if (lower.startsWith("space") || lower.startsWith("spacing"))
|
|
208
|
+
return "spacing";
|
|
209
|
+
if (lower.includes("size") || lower.includes("width") || lower.includes("height"))
|
|
210
|
+
return "sizing";
|
|
211
|
+
return "sizing";
|
|
212
|
+
}
|
|
213
|
+
return token.type;
|
|
214
|
+
}
|
|
215
|
+
function tsValueFor(value, token, warnings) {
|
|
216
|
+
if (value.reference) {
|
|
217
|
+
const bare = value.reference.replace(/^\{|\}$/g, "");
|
|
218
|
+
if (bare.startsWith("__library:") || bare === "unknown") {
|
|
219
|
+
warnings.push(`Skipped ${token.path.join(".")} in Tokens Studio — cross-library alias unresolved.`);
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
return `{${bare}}`;
|
|
223
|
+
}
|
|
224
|
+
if (value.literal === undefined || value.literal === null)
|
|
225
|
+
return undefined;
|
|
226
|
+
if (typeof value.literal === "number" && token.type === "dimension") {
|
|
227
|
+
return `${value.literal}px`;
|
|
228
|
+
}
|
|
229
|
+
return value.literal;
|
|
230
|
+
}
|
|
231
|
+
function sortKeys(node) {
|
|
232
|
+
if (node === null || typeof node !== "object" || Array.isArray(node)) {
|
|
233
|
+
return node;
|
|
234
|
+
}
|
|
235
|
+
const obj = node;
|
|
236
|
+
const sorted = {};
|
|
237
|
+
// $-prefixed keys first (matches Tokens Studio convention), then alphabetical.
|
|
238
|
+
const keys = Object.keys(obj).sort((a, b) => {
|
|
239
|
+
const aDollar = a.startsWith("$");
|
|
240
|
+
const bDollar = b.startsWith("$");
|
|
241
|
+
if (aDollar && !bDollar)
|
|
242
|
+
return -1;
|
|
243
|
+
if (!aDollar && bDollar)
|
|
244
|
+
return 1;
|
|
245
|
+
return a.localeCompare(b);
|
|
246
|
+
});
|
|
247
|
+
for (const k of keys)
|
|
248
|
+
sorted[k] = sortKeys(obj[k]);
|
|
249
|
+
return sorted;
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=tokens-studio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens-studio.js","sourceRoot":"","sources":["../../../../src/core/tokens/formatters/tokens-studio.ts"],"names":[],"mappings":"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"}
|