""" 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))