Add design-pattern-learner skill with auto-trigger

NEW SKILL: Design Pattern Learner
- Studies and implements web design patterns from external sources
- Fetches gists, repositories, and webpages
- Analyzes design tokens (colors, typography, spacing, effects)
- Extracts UI components (buttons, cards, modals, etc.)
- Generates implementation code (Tailwind, React, Vue)

Auto-Trigger Patterns:
- "study design from [URL]"
- "learn from [source]"
- "implement this design"
- "copy style from"
- "extract component from"

Integration:
- Works alongside ui-ux-pro-max for design guidance
- Uses codebase-indexer to find implementation locations
- Uses mcp-client for external content fetching
- Added to always-use-superpowers decision tree

Updated Files:
- skills/design-pattern-learner/skill.md - Complete skill documentation
- skills/design-pattern-learner/scripts/analyze.py - Pattern analyzer
- skills/design-pattern-learner/scripts/generate.py - Implementation generator
- skills/design-pattern-learner/README.md - Quick start guide
- ralph-integration/dispatch/auto-triggers.yml - Priority 7
- skills/always-use-superpowers/SKILL.md - Decision tree updated

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude SuperCharged
2026-01-26 13:51:53 +04:00
Unverified
parent 8ad918861a
commit 39e480484f
5 changed files with 1413 additions and 1 deletions

View File

@@ -0,0 +1,453 @@
#!/usr/bin/env python3
"""
Design Pattern Analyzer
Fetches and analyzes design patterns from external sources
"""
import sys
import json
import re
import os
from urllib.parse import urlparse
from datetime import datetime
import subprocess
class DesignPatternAnalyzer:
def __init__(self, source_url):
self.source_url = source_url
self.patterns = {
"source": source_url,
"timestamp": datetime.now().isoformat(),
"design_tokens": {},
"components": [],
"layouts": [],
"animations": []
}
def fetch_source(self):
"""Fetch content from URL/gist/repo"""
print(f"📥 Fetching source: {self.source_url}")
# Detect source type
if "gist.github.com" in self.source_url:
return self._fetch_gist()
elif "github.com" in self.source_url:
return self._fetch_github_repo()
else:
return self._fetch_webpage()
def _fetch_gist(self):
"""Fetch gist content using git"""
print("🔍 Detected: GitHub Gist")
# Extract gist ID
gist_match = re.search(r'gist\.github\.com/[^/]+/([a-f0-9]+)', self.source_url)
if not gist_match:
gist_match = re.search(r'gist\.github\.com/([a-f0-9]+)', self.source_url)
if gist_match:
gist_id = gist_match.group(1)
gist_url = f"https://gist.github.com/{gist_id}"
# Use curl to fetch
result = subprocess.run(
['curl', '-s', gist_url],
capture_output=True,
text=True
)
if result.returncode == 0:
return self._parse_gist_html(result.stdout)
else:
print(f"❌ Failed to fetch gist: {result.stderr}")
return None
else:
print("❌ Could not extract gist ID")
return None
def _fetch_github_repo(self):
"""Fetch GitHub repository"""
print("🔍 Detected: GitHub Repository")
print("⚠️ Repo analysis requires cloning - will analyze README and structure")
# For now, analyze the main page
result = subprocess.run(
['curl', '-s', self.source_url],
capture_output=True,
text=True
)
if result.returncode == 0:
return self._parse_github_page(result.stdout)
else:
print(f"❌ Failed to fetch repo: {result.stderr}")
return None
def _fetch_webpage(self):
"""Fetch regular webpage"""
print("🔍 Detected: Webpage")
result = subprocess.run(
['curl', '-s', '-L', self.source_url],
capture_output=True,
text=True
)
if result.returncode == 0:
return result.stdout
else:
print(f"❌ Failed to fetch webpage: {result.stderr}")
return None
def _parse_gist_html(self, html):
"""Parse gist HTML to extract code"""
print("📄 Parsing gist content...")
# Look for file content in gist HTML
# Extract from <div class="highlight"> or similar
file_pattern = r'<div class="[^"]*highlight[^"]*"[^>]*>(.*?)</div>'
files = re.findall(file_pattern, html, re.DOTALL)
if files:
# Clean up HTML entities and tags
content = []
for file_html in files:
# Remove HTML tags but keep code
clean_code = re.sub(r'<[^>]+>', '\n', file_html)
clean_code = re.sub(r'&lt;', '<', clean_code)
clean_code = re.sub(r'&gt;', '>', clean_code)
clean_code = re.sub(r'&amp;', '&', clean_code)
clean_code = re.sub(r'\n\s*\n', '\n', clean_code)
content.append(clean_code.strip())
return '\n\n'.join(content)
else:
print("⚠️ Could not extract gist files")
return html
def _parse_github_page(self, html):
"""Parse GitHub repo page"""
print("📄 Parsing repository page...")
return html
def analyze_design_tokens(self, content):
"""Extract design tokens from content"""
print("\n🎨 Extracting Design Tokens...")
tokens = {}
# Colors
colors = self._extract_colors(content)
if colors:
tokens['colors'] = colors
print(f" ✓ Found {len(colors)} color patterns")
# Typography
typography = self._extract_typography(content)
if typography:
tokens['typography'] = typography
print(f" ✓ Found {len(typography.get('fonts', []))} font patterns")
# Spacing
spacing = self._extract_spacing(content)
if spacing:
tokens['spacing'] = spacing
print(f" ✓ Found spacing patterns")
# Effects
effects = self._extract_effects(content)
if effects:
tokens['effects'] = effects
print(f" ✓ Found {len(effects.get('shadows', []))} shadow patterns")
self.patterns['design_tokens'] = tokens
return tokens
def _extract_colors(self, content):
"""Extract color patterns"""
colors = {}
# Hex colors
hex_colors = re.findall(r'#[0-9a-fA-F]{3,6}', content)
if hex_colors:
colors['hex'] = list(set(hex_colors))[:20] # Limit to 20 unique
# Tailwind color classes
tailwind_colors = re.findall(r'\b(bg|text|border)-([a-z]+)-(\d+)\b', content)
if tailwind_colors:
colors['tailwind'] = [
f"{prefix}-{color}-{shade}"
for prefix, color, shade in tailwind_colors
][:20]
# CSS color names
css_colors = re.findall(r'\b(black|white|gray|red|blue|green|yellow|purple|pink|indigo)\b', content, re.I)
if css_colors:
colors['css'] = list(set(css_colors))
return colors if colors else None
def _extract_typography(self, content):
"""Extract typography patterns"""
typo = {}
# Font families
fonts = re.findall(r'font-family:\s*([^;]+)', content, re.I)
if fonts:
typo['fonts'] = list(set(fonts))
# Font sizes
sizes = re.findall(r'(text-|font-)?size:\s*([^;]+)', content, re.I)
if sizes:
typo['sizes'] = list(set([s[1] for s in sizes]))
# Tailwind text classes
tailwind_text = re.findall(r'\b(text|font)-(xl|lg|md|sm|xs|\d)\b', content)
if tailwind_text:
typo['tailwind'] = [f"{prefix}-{size}" for prefix, size in tailwind_text]
return typo if typo else None
def _extract_spacing(self, content):
"""Extract spacing patterns"""
spacing = {}
# Tailwind spacing
tailwind_spacing = re.findall(r'\b(p|m|px|py|pt|pb|pl|pr)-(\\d+)\b', content)
if tailwind_spacing:
spacing['tailwind'] = list(set([f"{prefix}-{size}" for prefix, size in tailwind_spacing]))
# CSS spacing
css_spacing = re.findall(r'(padding|margin):\s*([^;]+)', content, re.I)
if css_spacing:
spacing['css'] = list(set([f"{prop}: {val}" for prop, val in css_spacing]))
return spacing if spacing else None
def _extract_effects(self, content):
"""Extract visual effects"""
effects = {}
# Shadows
shadows = re.findall(r'box-shadow:\s*([^;]+)', content, re.I)
if shadows:
effects['shadows'] = list(set(shadows))
# Tailwind shadows
tailwind_shadows = re.findall(r'\bshadow-(xl|lg|md|sm|none)\b', content)
if tailwind_shadows:
effects['tailwind_shadows'] = [f"shadow-{s}" for s in tailwind_shadows]
# Border radius
radius = re.findall(r'border-radius:\s*([^;]+)', content, re.I)
if radius:
effects['radius'] = list(set(radius))
return effects if effects else None
def analyze_components(self, content):
"""Extract UI components"""
print("\n🧩 Identifying Components...")
components = []
# Look for common component patterns
component_patterns = {
'button': r'<button[^>]*>.*?</button>|class="[^"]*button[^"]*"',
'card': r'class="[^"]*card[^"]*"',
'modal': r'class="[^"]*modal[^"]*"',
'nav': r'<nav[^>]*>.*?</nav>|class="[^"]*nav[^"]*"',
'form': r'<form[^>]*>.*?</form>|class="[^"]*form[^"]*"',
'input': r'<input[^>]*/?>|class="[^"]*input[^"]*"',
'hero': r'class="[^"]*hero[^"]*"',
'footer': r'<footer[^>]*>.*?</footer>',
'header': r'<header[^>]*>.*?</header>',
}
for comp_name, pattern in component_patterns.items():
matches = re.findall(pattern, content, re.DOTALL | re.IGNORECASE)
if matches:
components.append({
'type': comp_name,
'count': len(matches),
'examples': matches[:3] # First 3 examples
})
print(f" ✓ Found {len(matches)} {comp_name} component(s)")
self.patterns['components'] = components
return components
def analyze_layouts(self, content):
"""Extract layout patterns"""
print("\n📐 Analyzing Layouts...")
layouts = []
# Grid layouts
grids = re.findall(r'grid-cols-\\d+', content)
if grids:
layouts.append({
'type': 'grid',
'variants': list(set(grids))
})
print(f" ✓ Found grid layouts: {list(set(grids))}")
# Flexbox
flex_patterns = re.findall(r'flex-(row|col|wrap|nowrap)', content)
if flex_patterns:
layouts.append({
'type': 'flexbox',
'patterns': list(set(flex_patterns))
})
print(f" ✓ Found flexbox patterns: {list(set(flex_patterns))}")
# Containers
containers = re.findall(r'class="[^"]*container[^"]*"', content)
if containers:
layouts.append({
'type': 'container',
'count': len(containers)
})
print(f" ✓ Found {len(containers)} container(s)")
self.patterns['layouts'] = layouts
return layouts
def analyze_animations(self, content):
"""Extract animation patterns"""
print("\n✨ Analyzing Animations...")
animations = []
# Transitions
transitions = re.findall(r'transition(?:-[^:]*)?:\\s*([^;]+)', content, re.I)
if transitions:
animations.append({
'type': 'transition',
'patterns': list(set(transitions))[:10]
})
print(f" ✓ Found transitions: {len(set(transitions))}")
# Transforms
transforms = re.findall(r'transform:\\s*([^;]+)', content, re.I)
if transforms:
animations.append({
'type': 'transform',
'patterns': list(set(transforms))
})
print(f" ✓ Found transforms: {len(set(transforms))}")
# Keyframes
keyframes = re.findall(r'@keyframes\\s+(\\w+)', content)
if keyframes:
animations.append({
'type': 'keyframe',
'names': list(set(keyframes))
})
print(f" ✓ Found keyframes: {list(set(keyframes))}")
self.patterns['animations'] = animations
return animations
def save_patterns(self):
"""Save extracted patterns to file"""
# Create data directory if needed
data_dir = os.path.expanduser('~/.claude/skills/design-pattern-learner/data/patterns')
os.makedirs(data_dir, exist_ok=True)
# Generate filename from URL
safe_name = re.sub(r'[^a-zA-Z0-9]', '_', self.source_url)[:50]
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
filename = f"{safe_name}_{timestamp}.json"
filepath = os.path.join(data_dir, filename)
# Save patterns
with open(filepath, 'w') as f:
json.dump(self.patterns, f, indent=2)
print(f"\n💾 Patterns saved to: {filepath}")
# Also save to learning history
history_file = os.path.expanduser('~/.claude/skills/design-pattern-learner/learning-history.jsonl')
with open(history_file, 'a') as f:
f.write(json.dumps({
'timestamp': datetime.now().isoformat(),
'source': self.source_url,
'file': filename,
'patterns_count': len(self.patterns['components']),
'success': True
}) + '\n')
return filepath
def generate_summary(self):
"""Generate human-readable summary"""
print("\n" + "="*60)
print("📊 DESIGN PATTERN ANALYSIS SUMMARY")
print("="*60)
print(f"\n📍 Source: {self.source_url}")
print(f"🕐 Analyzed: {self.patterns['timestamp']}")
# Design tokens
if self.patterns['design_tokens']:
print("\n🎨 Design Tokens:")
for category, values in self.patterns['design_tokens'].items():
print(f"{category}: {len(values)} patterns")
# Components
if self.patterns['components']:
print(f"\n🧩 Components Found: {len(self.patterns['components'])}")
for comp in self.patterns['components']:
print(f"{comp['type']}: {comp['count']} instance(s)")
# Layouts
if self.patterns['layouts']:
print(f"\n📐 Layout Patterns: {len(self.patterns['layouts'])}")
for layout in self.patterns['layouts']:
print(f"{layout['type']}")
# Animations
if self.patterns['animations']:
print(f"\n✨ Animations: {len(self.patterns['animations'])}")
for anim in self.patterns['animations']:
print(f"{anim['type']}")
print("\n" + "="*60)
print("✅ Analysis Complete!")
print("="*60)
def main():
if len(sys.argv) < 2:
print("Usage: python3 analyze.py <URL>")
print("Example: python3 analyze.py https://gist.github.com/user/id")
sys.exit(1)
url = sys.argv[1]
analyzer = DesignPatternAnalyzer(url)
# Fetch content
content = analyzer.fetch_source()
if not content:
print("❌ Failed to fetch content")
sys.exit(1)
# Analyze patterns
analyzer.analyze_design_tokens(content)
analyzer.analyze_components(content)
analyzer.analyze_layouts(content)
analyzer.analyze_animations(content)
# Save results
filepath = analyzer.save_patterns()
# Show summary
analyzer.generate_summary()
print(f"\n💡 Next steps:")
print(f" • View patterns: cat {filepath}")
print(f" • Generate implementation: python3 generate.py --source {filepath}")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,502 @@
#!/usr/bin/env python3
"""
Pattern Implementation Generator
Generates implementation code from analyzed patterns
"""
import sys
import json
import os
from datetime import datetime
class PatternGenerator:
def __init__(self, pattern_file, framework='tailwind'):
self.pattern_file = pattern_file
self.framework = framework
self.patterns = None
def load_patterns(self):
"""Load pattern JSON file"""
print(f"📖 Loading patterns from: {self.pattern_file}")
try:
with open(self.pattern_file, 'r') as f:
self.patterns = json.load(f)
print(f"✅ Patterns loaded successfully")
return True
except Exception as e:
print(f"❌ Error loading patterns: {e}")
return False
def generate_component_library(self):
"""Generate component library from patterns"""
print(f"\n🧩 Generating Component Library for {self.framework}...")
if not self.patterns.get('components'):
print("⚠️ No components found in patterns")
return {}
library = {}
for comp in self.patterns['components']:
comp_type = comp['type']
examples = comp.get('examples', [])
if not examples:
continue
library[comp_type] = {
'count': comp['count'],
'implementations': []
}
for i, example in enumerate(examples[:2]): # Max 2 examples
impl = self._convert_to_framework(comp_type, example)
if impl:
library[comp_type]['implementations'].append(impl)
print(f" ✓ Generated {comp_type} component")
return library
def _convert_to_framework(self, comp_type, html_snippet):
"""Convert HTML snippet to target framework"""
# Clean up the snippet
snippet = html_snippet.strip()
if self.framework == 'tailwind':
return self._convert_tailwind(comp_type, snippet)
elif self.framework == 'react':
return self._convert_react(comp_type, snippet)
elif self.framework == 'vue':
return self._convert_vue(comp_type, snippet)
else:
return {'html': snippet}
def _convert_tailwind(self, comp_type, snippet):
"""Convert to Tailwind HTML"""
# Extract classes if present
import re
classes = re.findall(r'class="([^"]*)"', snippet)
all_classes = ' '.join(classes) if classes else ''
return {
'framework': 'tailwind',
'html': snippet,
'classes': all_classes,
'usage': f'<!-- Copy this HTML for your {comp_type} -->'
}
def _convert_react(self, comp_type, snippet):
"""Convert to React component"""
import re
# Extract classes
classes = re.findall(r'class="([^"]*)"', snippet)
# Convert to JSX
jsx = snippet
# Replace class with className
jsx = re.sub(r'class=', 'className=', jsx)
# Close self-closing tags
jsx = re.sub(r'<input([^>]*)>', r'<input\1 />', jsx)
component_name = ''.join([w.capitalize() for w in comp_type.split('_')])
return {
'framework': 'react',
'component_name': component_name,
'jsx': jsx,
'code': f'''export function {component_name}() {{
return (
{self._indent_jsx(jsx, 4)}
);
}}'''
}
def _convert_vue(self, comp_type, snippet):
"""Convert to Vue component"""
component_name = ''.join([w.capitalize() for w in comp_type.split('_')])
return {
'framework': 'vue',
'component_name': component_name,
'template': snippet,
'code': f'''<template>
{self._indent_jsx(snippet, 2)}
</template>
<script setup>
// {component_name} component
</script>'''
}
def _indent_jsx(self, code, spaces):
"""Indent multi-line JSX/Vue code"""
lines = code.split('\n')
indent = ' ' * spaces
return '\n'.join([indent + line if line.strip() else line for line in lines])
def generate_design_system(self):
"""Generate design system from tokens"""
print(f"\n🎨 Generating Design System...")
if not self.patterns.get('design_tokens'):
print("⚠️ No design tokens found")
return {}
tokens = self.patterns['design_tokens']
design_system = {}
# Colors
if 'colors' in tokens:
design_system['colors'] = self._generate_color_tokens(tokens['colors'])
# Typography
if 'typography' in tokens:
design_system['typography'] = self._generate_typography_tokens(tokens['typography'])
# Spacing
if 'spacing' in tokens:
design_system['spacing'] = self._generate_spacing_tokens(tokens['spacing'])
# Effects
if 'effects' in tokens:
design_system['effects'] = self._generate_effect_tokens(tokens['effects'])
return design_system
def _generate_color_tokens(self, colors):
"""Generate color tokens"""
tokens = {'tailwind': {}, 'hex': {}}
if 'tailwind' in colors:
# Group by color name
for color_class in colors['tailwind']:
parts = color_class.split('-')
if len(parts) >= 3:
prop, color, shade = parts[0], parts[1], parts[2]
if color not in tokens['tailwind']:
tokens['tailwind'][color] = []
tokens['tailwind'][color].append(shade)
if 'hex' in colors:
tokens['hex'] = colors['hex'][:10] # Limit to 10
return tokens
def _generate_typography_tokens(self, typography):
"""Generate typography tokens"""
tokens = {}
if 'fonts' in typography:
tokens['font_families'] = typography['fonts']
if 'sizes' in typography:
tokens['font_sizes'] = typography['sizes']
if 'tailwind' in typography:
tokens['tailwind_classes'] = typography['tailwind']
return tokens
def _generate_spacing_tokens(self, spacing):
"""Generate spacing tokens"""
tokens = {}
if 'tailwind' in spacing:
# Extract unique spacing values
values = set()
for class_name in spacing['tailwind']:
parts = class_name.split('-')
if len(parts) >= 2:
values.add(parts[-1])
tokens['tailwind_scale'] = list(values)
if 'css' in spacing:
tokens['css_values'] = spacing['css'][:5]
return tokens
def _generate_effect_tokens(self, effects):
"""Generate effect tokens"""
tokens = {}
if 'shadows' in effects:
tokens['box_shadows'] = effects['shadows'][:5]
if 'tailwind_shadows' in effects:
tokens['tailwind_shadows'] = effects['tailwind_shadows']
if 'radius' in effects:
tokens['border_radius'] = effects['radius']
return tokens
def generate_implementation_guide(self):
"""Generate implementation guide"""
print(f"\n📖 Generating Implementation Guide...")
source = self.patterns.get('source', 'Unknown')
timestamp = self.patterns.get('timestamp', datetime.now().isoformat())
guide = f'''# Design Pattern Implementation Guide
**Source:** {source}
**Analyzed:** {timestamp}
**Framework:** {self.framework}
## Quick Start
1. Review the design tokens below
2. Copy component code for your needs
3. Integrate into your project
4. Customize as needed
---
## Design System
### Colors
{self._format_colors()}
### Typography
{self._format_typography()}
### Spacing
{self._format_spacing()}
### Effects
{self._format_effects()}
---
## Components
{self._format_components()}
---
## Usage Examples
### Applying Design Tokens
```{self.framework}
<!-- Example with design tokens -->
<div class="bg-primary-500 text-white p-4 rounded-lg shadow-lg">
Content here
</div>
```
### Using Components
Copy any component from the Components section above and adapt to your needs.
---
## Customization
### Modify Colors
Update your Tailwind config or CSS variables to match the design tokens.
### Adjust Spacing
Scale spacing values up or down based on your design system.
### Add Effects
Apply the shadow and radius patterns to other components.
---
## Attribution
This implementation is based on design patterns from: {source}
Please respect the original source's license and attribution requirements.
---
**Generated by:** Design Pattern Learner v1.0
**Date:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
'''
return guide
def _format_colors(self):
"""Format colors for guide"""
if not self.patterns.get('design_tokens', {}).get('colors'):
return 'No color patterns found'
colors = self.patterns['design_tokens']['colors']
lines = []
if 'tailwind' in colors:
lines.append('\n**Tailwind Colors:**')
for color in list(colors['tailwind'])[:10]:
lines.append(f'- `{color}`')
if 'hex' in colors:
lines.append('\n**Hex Colors:**')
for hex_color in colors['hex'][:10]:
lines.append(f'- `{hex_color}`')
return '\n'.join(lines)
def _format_typography(self):
"""Format typography for guide"""
if not self.patterns.get('design_tokens', {}).get('typography'):
return 'No typography patterns found'
typo = self.patterns['design_tokens']['typography']
lines = []
if 'fonts' in typo:
lines.append('\n**Font Families:**')
for font in typo['fonts'][:5]:
lines.append(f'- `{font}`')
if 'tailwind' in typo:
lines.append('\n**Tailwind Text Classes:**')
for cls in typo['tailwind'][:10]:
lines.append(f'- `{cls}`')
return '\n'.join(lines)
def _format_spacing(self):
"""Format spacing for guide"""
if not self.patterns.get('design_tokens', {}).get('spacing'):
return 'No spacing patterns found'
spacing = self.patterns['design_tokens']['spacing']
lines = []
if 'tailwind' in spacing:
lines.append('\n**Tailwind Spacing:**')
for cls in list(spacing['tailwind'])[:10]:
lines.append(f'- `{cls}`')
return '\n'.join(lines)
def _format_effects(self):
"""Format effects for guide"""
if not self.patterns.get('design_tokens', {}).get('effects'):
return 'No effect patterns found'
effects = self.patterns['design_tokens']['effects']
lines = []
if 'shadows' in effects:
lines.append('\n**Box Shadows:**')
for shadow in effects['shadows'][:5]:
lines.append(f'- `{shadow}`')
return '\n'.join(lines)
def _format_components(self):
"""Format components for guide"""
if not self.patterns.get('components'):
return 'No components found'
library = self.generate_component_library()
lines = []
for comp_name, comp_data in library.items():
lines.append(f'\n### {comp_name.capitalize()}')
lines.append(f'\nFound: {comp_data["count"]} instance(s)')
for impl in comp_data.get('implementations', [])[:2]:
if self.framework == 'tailwind':
lines.append(f'\n```html')
lines.append(impl.get('html', ''))
lines.append('```')
elif self.framework == 'react':
lines.append(f'\n```jsx')
lines.append(impl.get('code', ''))
lines.append('```')
elif self.framework == 'vue':
lines.append(f'\n```vue')
lines.append(impl.get('code', ''))
lines.append('```')
return '\n'.join(lines)
def save_outputs(self, library, design_system, guide):
"""Save generated outputs"""
output_dir = os.path.expanduser('~/.claude/skills/design-pattern-learner/data/outputs')
os.makedirs(output_dir, exist_ok=True)
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
# Save component library
library_file = os.path.join(output_dir, f'library_{self.framework}_{timestamp}.json')
with open(library_file, 'w') as f:
json.dump(library, f, indent=2)
print(f'\n💾 Component library: {library_file}')
# Save design system
system_file = os.path.join(output_dir, f'design-system_{self.framework}_{timestamp}.json')
with open(system_file, 'w') as f:
json.dump(design_system, f, indent=2)
print(f'💾 Design system: {system_file}')
# Save implementation guide
guide_file = os.path.join(output_dir, f'implementation-guide_{self.framework}_{timestamp}.md')
with open(guide_file, 'w') as f:
f.write(guide)
print(f'💾 Implementation guide: {guide_file}')
return library_file, system_file, guide_file
def main():
if len(sys.argv) < 3:
print("Usage: python3 generate.py --source <pattern_file> --framework <tailwind|react|vue>")
print("Example: python3 generate.py --source patterns.json --framework tailwind")
sys.exit(1)
pattern_file = None
framework = 'tailwind'
args = sys.argv[1:]
i = 0
while i < len(args):
if args[i] == '--source' and i + 1 < len(args):
pattern_file = args[i + 1]
i += 2
elif args[i] == '--framework' and i + 1 < len(args):
framework = args[i + 1].lower()
i += 2
else:
i += 1
if not pattern_file:
print("❌ Error: --source parameter is required")
sys.exit(1)
if framework not in ['tailwind', 'react', 'vue']:
print(f"⚠️ Warning: Unknown framework '{framework}', using 'tailwind'")
framework = 'tailwind'
generator = PatternGenerator(pattern_file, framework)
if not generator.load_patterns():
sys.exit(1)
print(f"\n{'='*60}")
print(f"🚀 GENERATING IMPLEMENTATION FOR {framework.upper()}")
print(f"{'='*60}")
# Generate outputs
library = generator.generate_component_library()
design_system = generator.generate_design_system()
guide = generator.generate_implementation_guide()
# Save outputs
generator.save_outputs(library, design_system, guide)
print(f"\n{'='*60}")
print("✅ GENERATION COMPLETE!")
print(f"{'='*60}")
if __name__ == '__main__':
main()