#!/usr/bin/env python3 """ FOSScard - Generate Magic-style cards for your open source contributions Usage: python fosscard.py profile.yaml > output.html cat profile.yaml | python fosscard.py > output.html """ import sys import yaml from pathlib import Path STYLES = { 'dark': { 'bg_gradient': 'linear-gradient(135deg, #000000 0%, #0a0a0a 100%)', 'card_bg': 'linear-gradient(to bottom, #0d0d0d 0%, #050505 100%)', 'border_color': '#8b7355', 'text_color': '#e8e8e8', 'header_color': '#8b7355', 'section_bg': 'rgba(139, 115, 85, 0.1)', 'accent': '#9d8362' }, 'light': { 'bg_gradient': 'linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%)', 'card_bg': 'linear-gradient(to bottom, #ffffff 0%, #f1f3f5 100%)', 'border_color': '#495057', 'text_color': '#212529', 'header_color': '#495057', 'section_bg': 'rgba(73, 80, 87, 0.05)', 'accent': '#228be6' }, 'matrix': { 'bg_gradient': 'linear-gradient(135deg, #0d0208 0%, #001b1c 100%)', 'card_bg': 'linear-gradient(to bottom, #003b00 0%, #001b00 100%)', 'border_color': '#00ff41', 'text_color': '#00ff41', 'header_color': '#00ff41', 'section_bg': 'rgba(0, 255, 65, 0.1)', 'accent': '#00cc33' }, 'molokai': { 'bg_gradient': 'linear-gradient(135deg, #1B1D1E 0%, #232526 100%)', 'card_bg': 'linear-gradient(to bottom, #272822 0%, #1e1f1c 100%)', 'border_color': '#66D9EF', 'text_color': '#F8F8F2', 'header_color': '#F92672', 'section_bg': 'rgba(102, 217, 239, 0.08)', 'accent': '#A6E22E' } } def generate_html(data): """Generate HTML for the FOSScard""" name = data.get('name', 'Anonymous Developer') name_link = data.get('link', '') logo = data.get('logo', '') header_background = data.get('header_background', '') # If header_background is a URL (not already wrapped in url()), wrap it if header_background and (header_background.startswith('http://') or header_background.startswith('https://')): if not header_background.startswith('url('): header_background = f"url('{header_background}')" style_name = data.get('style', 'dark').lower() style = STYLES.get(style_name, STYLES['dark']) projects = data.get('projects', {}) # Build project sections HTML projects_html = '' for category, content in projects.items(): projects_html += f'
{category}
' for item_name, item_details in content.items(): if isinstance(item_details, dict): # Check if this is a direct project or a language grouping if 'link' in item_details or 'description' in item_details: # Direct project under category link = item_details.get('link', '') desc = item_details.get('description', '') complexity = item_details.get('complexity', 0) # Choose color based on complexity level if complexity < 3: complexity_indicator = '🟩' * complexity elif complexity < 5: complexity_indicator = '🟨' * complexity elif complexity > 4: complexity_indicator = '🟥' * complexity else: complexity_indicator = '' if link: project_name_html = f'{item_name}' else: project_name_html = f'{item_name}' if complexity_indicator: project_name_html += f' {complexity_indicator}' projects_html += f'''
{project_name_html} {desc}
''' else: # Language grouping with projects underneath projects_html += f'
{item_name}
' for proj_name, proj_details in item_details.items(): if isinstance(proj_details, dict): link = proj_details.get('link', '') desc = proj_details.get('description', '') complexity = proj_details.get('complexity', 0) # Choose color based on complexity level if complexity >= 5: complexity_indicator = '🟥' * complexity elif 3 <= complexity <= 4: complexity_indicator = '🟨' * complexity elif 1 <= complexity <= 2: complexity_indicator = '🟩' * complexity else: complexity_indicator = '' if link: project_name_html = f'{proj_name}' else: project_name_html = f'{proj_name}' if complexity_indicator: project_name_html += f' {complexity_indicator}' projects_html += f'''
{project_name_html} {desc}
''' html = f''' {name} - FOSScard
{f'' if logo else ''}
{f'{name}' if name_link else name}
{projects_html}
''' return html def main(): """Main entry point""" # Check if input is from stdin or file argument if len(sys.argv) > 1: yaml_file = Path(sys.argv[1]) if not yaml_file.exists(): print(f"Error: File '{yaml_file}' not found", file=sys.stderr) sys.exit(1) with open(yaml_file, 'r') as f: data = yaml.safe_load(f) else: # Read from stdin data = yaml.safe_load(sys.stdin) html = generate_html(data) print(html) if __name__ == '__main__': main()