Files
dss/tools/api/tokens/exporters.py
Digital Production Factory 276ed71f31 Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm

Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)

Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability

Migration completed: $(date)
🤖 Clean migration with full functionality preserved
2025-12-09 18:45:48 -03:00

375 lines
11 KiB
Python

"""
Token Format Exporters
Export design tokens extracted from Figma in multiple formats:
- CSS Variables
- JSON
- TypeScript
- SCSS
- JavaScript
"""
import json
from typing import Dict, Any, List
from pathlib import Path
class TokenExporter:
"""Base class for token exporters"""
def __init__(self, tokens: Dict[str, Any]):
"""Initialize exporter with tokens"""
self.tokens = tokens
self.output = ""
def export(self) -> str:
"""Export tokens in format-specific way"""
raise NotImplementedError
class CSSVariableExporter(TokenExporter):
"""Export tokens as CSS custom properties"""
def export(self) -> str:
"""Export as CSS variables"""
lines = [":root {"]
if "colors" in self.tokens:
for name, value in self.tokens["colors"].items():
lines.append(f" --color-{name}: {value};")
if "spacing" in self.tokens:
for name, value in self.tokens["spacing"].items():
lines.append(f" --spacing-{name}: {value}px;")
if "typography" in self.tokens:
for name, props in self.tokens["typography"].items():
if isinstance(props, dict):
for prop, val in props.items():
lines.append(f" --typography-{name}-{prop}: {val};")
else:
lines.append(f" --typography-{name}: {props};")
lines.append("}")
return "\n".join(lines)
class JSONExporter(TokenExporter):
"""Export tokens as JSON"""
def export(self) -> str:
"""Export as JSON"""
return json.dumps(self.tokens, indent=2)
class TypeScriptExporter(TokenExporter):
"""Export tokens as TypeScript constants"""
def export(self) -> str:
"""Export as TypeScript"""
lines = [
"/**",
" * Design System Tokens",
" * Auto-generated from Figma",
" */",
"",
"export const DSSTokens = {"
]
# Colors
if "colors" in self.tokens:
lines.append(" colors: {")
for name, value in self.tokens["colors"].items():
lines.append(f" {name}: '{value}',")
lines.append(" },")
# Spacing
if "spacing" in self.tokens:
lines.append(" spacing: {")
for name, value in self.tokens["spacing"].items():
lines.append(f" {name}: {value},")
lines.append(" },")
# Typography
if "typography" in self.tokens:
lines.append(" typography: {")
for name, props in self.tokens["typography"].items():
if isinstance(props, dict):
lines.append(f" {name}: {{")
for prop, val in props.items():
if isinstance(val, str):
lines.append(f" {prop}: '{val}',")
else:
lines.append(f" {prop}: {val},")
lines.append(" },")
else:
lines.append(f" {name}: '{props}',")
lines.append(" },")
lines.append("};")
lines.append("")
lines.append("export type TokenKey = keyof typeof DSSTokens;")
return "\n".join(lines)
class SCSSExporter(TokenExporter):
"""Export tokens as SCSS variables"""
def export(self) -> str:
"""Export as SCSS"""
lines = ["// Design System Tokens - SCSS Variables", ""]
# Colors
if "colors" in self.tokens:
lines.append("// Colors")
for name, value in self.tokens["colors"].items():
lines.append(f"$color-{name}: {value};")
lines.append("")
# Spacing
if "spacing" in self.tokens:
lines.append("// Spacing")
for name, value in self.tokens["spacing"].items():
lines.append(f"$spacing-{name}: {value}px;")
lines.append("")
# Typography
if "typography" in self.tokens:
lines.append("// Typography")
for name, props in self.tokens["typography"].items():
if isinstance(props, dict):
for prop, val in props.items():
lines.append(f"$typography-{name}-{prop}: {val};")
else:
lines.append(f"$typography-{name}: {props};")
lines.append("")
return "\n".join(lines)
class JavaScriptExporter(TokenExporter):
"""Export tokens as JavaScript object"""
def export(self) -> str:
"""Export as JavaScript"""
lines = [
"/**",
" * Design System Tokens",
" * Auto-generated from Figma",
" */",
"",
"const DSSTokens = {"
]
# Colors
if "colors" in self.tokens:
lines.append(" colors: {")
for name, value in self.tokens["colors"].items():
lines.append(f" {name}: '{value}',")
lines.append(" },")
# Spacing
if "spacing" in self.tokens:
lines.append(" spacing: {")
for name, value in self.tokens["spacing"].items():
lines.append(f" {name}: {value},")
lines.append(" },")
# Typography
if "typography" in self.tokens:
lines.append(" typography: {")
for name, props in self.tokens["typography"].items():
if isinstance(props, dict):
lines.append(f" {name}: {{")
for prop, val in props.items():
if isinstance(val, str):
lines.append(f" {prop}: '{val}',")
else:
lines.append(f" {prop}: {val},")
lines.append(" },")
else:
lines.append(f" {name}: '{props}',")
lines.append(" },")
lines.append("};")
lines.append("")
lines.append("module.exports = DSSTokens;")
return "\n".join(lines)
class FigmaExporter(TokenExporter):
"""Export tokens in Figma sync format"""
def export(self) -> str:
"""Export in Figma-compatible format"""
figma_tokens = {
"colors": [],
"typography": [],
"sizing": []
}
if "colors" in self.tokens:
for name, value in self.tokens["colors"].items():
figma_tokens["colors"].append({
"name": name,
"value": value,
"type": "color"
})
if "spacing" in self.tokens:
for name, value in self.tokens["spacing"].items():
figma_tokens["sizing"].append({
"name": name,
"value": f"{value}px",
"type": "size"
})
if "typography" in self.tokens:
for name, props in self.tokens["typography"].items():
figma_tokens["typography"].append({
"name": name,
"value": props,
"type": "typography"
})
return json.dumps(figma_tokens, indent=2)
class TailwindExporter(TokenExporter):
"""Export tokens as Tailwind configuration"""
def export(self) -> str:
"""Export as Tailwind config"""
lines = [
"/**",
" * Tailwind Configuration",
" * Auto-generated from Design System tokens",
" */",
"",
"module.exports = {",
" theme: {",
" extend: {"
]
# Colors
if "colors" in self.tokens:
lines.append(" colors: {")
for name, value in self.tokens["colors"].items():
lines.append(f" '{name}': '{value}',")
lines.append(" },")
# Spacing
if "spacing" in self.tokens:
lines.append(" spacing: {")
for name, value in self.tokens["spacing"].items():
lines.append(f" '{name}': '{value}px',")
lines.append(" },")
lines.append(" },")
lines.append(" },")
lines.append("};")
return "\n".join(lines)
class TokenExporterFactory:
"""Factory for creating exporters"""
exporters = {
"css": CSSVariableExporter,
"json": JSONExporter,
"typescript": TypeScriptExporter,
"ts": TypeScriptExporter,
"scss": SCSSExporter,
"javascript": JavaScriptExporter,
"js": JavaScriptExporter,
"figma": FigmaExporter,
"tailwind": TailwindExporter,
}
@classmethod
def create(cls, format: str, tokens: Dict[str, Any]) -> TokenExporter:
"""Create exporter for specified format"""
exporter_class = cls.exporters.get(format.lower())
if not exporter_class:
raise ValueError(f"Unknown export format: {format}")
return exporter_class(tokens)
@classmethod
def export(cls, format: str, tokens: Dict[str, Any]) -> str:
"""Export tokens directly"""
exporter = cls.create(format, tokens)
return exporter.export()
@classmethod
def export_all(cls, tokens: Dict[str, Any], output_dir: Path) -> Dict[str, Path]:
"""Export tokens in all formats to directory"""
output_dir.mkdir(parents=True, exist_ok=True)
results = {}
format_extensions = {
"css": ".css",
"json": ".json",
"typescript": ".ts",
"scss": ".scss",
"javascript": ".js",
"figma": ".figma.json",
"tailwind": ".config.js",
}
for format, ext in format_extensions.items():
try:
exported = cls.export(format, tokens)
filename = f"tokens{ext}"
filepath = output_dir / filename
with open(filepath, "w") as f:
f.write(exported)
results[format] = filepath
except Exception as e:
print(f"Error exporting {format}: {e}")
return results
# Convenience functions
def export_tokens_css(tokens: Dict[str, Any]) -> str:
"""Export tokens as CSS variables"""
return TokenExporterFactory.export("css", tokens)
def export_tokens_json(tokens: Dict[str, Any]) -> str:
"""Export tokens as JSON"""
return TokenExporterFactory.export("json", tokens)
def export_tokens_typescript(tokens: Dict[str, Any]) -> str:
"""Export tokens as TypeScript"""
return TokenExporterFactory.export("typescript", tokens)
def export_tokens_scss(tokens: Dict[str, Any]) -> str:
"""Export tokens as SCSS"""
return TokenExporterFactory.export("scss", tokens)
def export_tokens_javascript(tokens: Dict[str, Any]) -> str:
"""Export tokens as JavaScript"""
return TokenExporterFactory.export("javascript", tokens)
def export_tokens_tailwind(tokens: Dict[str, Any]) -> str:
"""Export tokens for Tailwind"""
return TokenExporterFactory.export("tailwind", tokens)
def export_all_formats(tokens: Dict[str, Any], output_dir: str) -> Dict[str, Path]:
"""Export tokens in all formats"""
return TokenExporterFactory.export_all(tokens, Path(output_dir))