#!/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'' } 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']*)>', r'', 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''' ''' } 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}
Content here
``` ### 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 --framework ") 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()