""" Code Formatter & Syntax Highlighter Module for AumCore AI Version: 1.0.0 Author: AumCore AI Location: /app/modules/code_formatter.py """ import re import json import html from typing import Dict, List, Optional, Tuple, Any from enum import Enum from dataclasses import dataclass, field from fastapi import APIRouter, HTTPException from fastapi.responses import HTMLResponse, JSONResponse import pygments from pygments import lexers, formatters, styles from pygments.lexers import ( PythonLexer, JavascriptLexer, HtmlLexer, CssLexer, SqlLexer, JavaLexer, CLexer, CppLexer, GoLexer, RustLexer, PhpLexer, RubyLexer, SwiftLexer ) import base64 import uuid from datetime import datetime import os class CodeLanguage(Enum): """Supported programming languages for formatting""" PYTHON = "python" JAVASCRIPT = "javascript" HTML = "html" CSS = "css" SQL = "sql" JAVA = "java" C = "c" CPP = "cpp" GO = "go" RUST = "rust" PHP = "php" RUBY = "ruby" SWIFT = "swift" JSON = "json" YAML = "yaml" MARKDOWN = "markdown" BASH = "bash" class CodeTheme(Enum): """Available color themes""" MONOKAI = "monokai" VSCODE = "vscode" SOLARIZED = "solarized" DRACULA = "dracula" GITHUB = "github" VS = "vs" XCODE = "xcode" @dataclass class FormatOptions: """Code formatting options""" theme: CodeTheme = CodeTheme.MONOKAI show_line_numbers: bool = True show_copy_button: bool = True show_download_button: bool = True language_label: bool = True max_height: Optional[str] = "500px" border_radius: str = "8px" font_family: str = "'Fira Code', 'Consolas', monospace" font_size: str = "14px" class AumCoreCodeFormatter: """ Advanced Code Formatter with Syntax Highlighting Creates beautiful, interactive code blocks """ def __init__(self): self._lexer_map = self._create_lexer_map() self._theme_styles = self._load_theme_styles() self._code_cache: Dict[str, str] = {} def _create_lexer_map(self) -> Dict[str, Any]: """Create mapping from language names to Pygments lexers""" return { "python": PythonLexer(), "javascript": JavascriptLexer(), "js": JavascriptLexer(), "html": HtmlLexer(), "css": CssLexer(), "sql": SqlLexer(), "java": JavaLexer(), "c": CLexer(), "cpp": CppLexer(), "c++": CppLexer(), "go": GoLexer(), "rust": RustLexer(), "php": PhpLexer(), "ruby": RubyLexer(), "swift": SwiftLexer(), "json": lexers.JsonLexer(), "yaml": lexers.YamlLexer(), "markdown": lexers.MarkdownLexer(), "bash": lexers.BashLexer(), "shell": lexers.BashLexer(), "sh": lexers.BashLexer(), } def _load_theme_styles(self) -> Dict[str, Dict]: """Load color styles for different themes""" return { "monokai": { "background": "#272822", "foreground": "#f8f8f2", "line_numbers": "#75715e", "line_numbers_bg": "#272822", "border": "#49483e", "button_bg": "#49483e", "button_hover": "#5a594e", "button_text": "#f8f8f2", "header_bg": "#49483e", "header_text": "#f8f8f2", "keyword": "#f92672", "string": "#e6db74", "comment": "#75715e", "number": "#ae81ff", "function": "#a6e22e", "class": "#a6e22e", "operator": "#f8f8f2", }, "vscode": { "background": "#1e1e1e", "foreground": "#d4d4d4", "line_numbers": "#858585", "line_numbers_bg": "#1e1e1e", "border": "#252526", "button_bg": "#007acc", "button_hover": "#1a8cff", "button_text": "#ffffff", "header_bg": "#252526", "header_text": "#cccccc", "keyword": "#569cd6", "string": "#ce9178", "comment": "#6a9955", "number": "#b5cea8", "function": "#dcdcaa", "class": "#4ec9b0", "operator": "#d4d4d4", }, "github": { "background": "#f6f8fa", "foreground": "#24292e", "line_numbers": "#6a737d", "line_numbers_bg": "#f6f8fa", "border": "#e1e4e8", "button_bg": "#0366d6", "button_hover": "#005cc5", "button_text": "#ffffff", "header_bg": "#f6f8fa", "header_text": "#24292e", "keyword": "#d73a49", "string": "#032f62", "comment": "#6a737d", "number": "#005cc5", "function": "#6f42c1", "class": "#22863a", "operator": "#24292e", } } def detect_language(self, code: str, hint: str = None) -> str: """ Detect programming language from code Args: code: Source code hint: Optional language hint Returns: Detected language name """ if hint and hint.lower() in self._lexer_map: return hint.lower() # Try to auto-detect try: lexer = lexers.guess_lexer(code) for lang_name, lexer_obj in self._lexer_map.items(): if isinstance(lexer, type(lexer_obj)): return lang_name except: pass # Fallback based on code patterns code_lower = code.lower() if re.search(r'def\s+\w+\(|import\s+\w+|from\s+\w+', code_lower): return "python" elif re.search(r'function\s+\w+|const\s+\w+=|let\s+\w+=', code_lower): return "javascript" elif re.search(r' str: """ Format code as HTML with syntax highlighting Args: code: Source code to format language: Programming language (auto-detected if None) options: Formatting options Returns: HTML code block """ options = options or FormatOptions() # Detect language if not provided lang = language.lower() if language else self.detect_language(code) if lang not in self._lexer_map: lang = "python" # Default fallback # Generate unique ID for this code block block_id = f"codeblock-{uuid.uuid4().hex[:8]}" # Get theme colors theme_name = options.theme.value theme = self._theme_styles.get(theme_name, self._theme_styles["monokai"]) # Generate highlighted code highlighted_code = self._highlight_code(code, lang, theme_name) # Build HTML html_output = self._build_code_block_html( code=highlighted_code, raw_code=code, language=lang, block_id=block_id, theme=theme, options=options ) # Cache for potential reuse cache_key = f"{lang}:{hash(code)}" self._code_cache[cache_key] = html_output return html_output def _highlight_code(self, code: str, language: str, theme: str) -> str: """ Highlight code using Pygments Args: code: Source code language: Programming language theme: Color theme Returns: HTML with syntax highlighting """ try: lexer = self._lexer_map.get(language, PythonLexer()) # Use appropriate formatter if theme == "monokai": style = styles.get_style_by_name("monokai") elif theme == "solarized": style = styles.get_style_by_name("solarized-dark") else: style = styles.get_style_by_name("default") formatter = formatters.HtmlFormatter( style=style, linenos=False, cssclass="", noclasses=False, prestyles="margin: 0;" ) highlighted = pygments.highlight(code, lexer, formatter) # Extract just the
 part
            highlighted = highlighted.replace('class="highlight"', '')
            highlighted = highlighted.replace('
', '').replace('
', '') highlighted = highlighted.replace('
', '').replace('
', '') return highlighted.strip() except Exception as e: # Fallback: basic HTML escape return f'{html.escape(code)}' def _build_code_block_html(self, code: str, raw_code: str, language: str, block_id: str, theme: Dict, options: FormatOptions) -> str: """ Build complete code block HTML with controls Args: code: Highlighted code HTML raw_code: Original raw code language: Programming language block_id: Unique block ID theme: Theme colors dictionary options: Formatting options Returns: Complete HTML code block """ # Language display name lang_display = language.upper() if language == "python" else language.title() # Line numbers HTML line_numbers = "" if options.show_line_numbers: lines = raw_code.split('\n') line_numbers_html = [] for i in range(1, len(lines) + 1): line_numbers_html.append(f'{i}') line_numbers = f'
{chr(10).join(line_numbers_html)}
' # Buttons HTML buttons_html = "" if options.show_copy_button or options.show_download_button: buttons = [] if options.show_copy_button: buttons.append(f''' ''') if options.show_download_button: # Encode code for download encoded_code = base64.b64encode(raw_code.encode()).decode() filename = f"code_{language}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.{language}" buttons.append(f''' Download ''') if buttons: buttons_html = f'
{chr(10).join(buttons)}
' # Header HTML header_html = "" if options.language_label or buttons_html: header_parts = [] if options.language_label: header_parts.append(f'
{lang_display}
') if buttons_html: header_parts.append(buttons_html) header_html = f'
{chr(10).join(header_parts)}
' # CSS Styles css_styles = f''' ''' # JavaScript for copy functionality js_script = f''' ''' # Build final HTML html_structure = f'''
{css_styles} {header_html}
{line_numbers}
{code}
{js_script}
''' return html_structure.strip() def format_multiple_codes(self, code_blocks: List[Dict], options: FormatOptions = None) -> str: """ Format multiple code blocks at once Args: code_blocks: List of dicts with 'code' and optional 'language' options: Formatting options Returns: Combined HTML with all code blocks """ html_blocks = [] for i, block in enumerate(code_blocks): code = block.get('code', '') language = block.get('language') if code.strip(): html_block = self.format_code_html(code, language, options) html_blocks.append(html_block) return '\n'.join(html_blocks) # Global instance code_formatter = AumCoreCodeFormatter() # FastAPI Router for module registration def register_module(app, client, username): """Register code formatter module with FastAPI app""" router = APIRouter() @router.get("/code/format") async def format_code_endpoint( code: str, language: str = None, theme: str = "monokai", line_numbers: bool = True, copy_button: bool = True, download_button: bool = True ): """API endpoint to format code""" try: options = FormatOptions( theme=CodeTheme(theme) if theme in [t.value for t in CodeTheme] else CodeTheme.MONOKAI, show_line_numbers=line_numbers, show_copy_button=copy_button, show_download_button=download_button ) html_output = code_formatter.format_code_html(code, language, options) return HTMLResponse(content=html_output) except Exception as e: raise HTTPException(status_code=400, detail=f"Formatting error: {str(e)}") @router.get("/code/detect") async def detect_language_endpoint(code: str): """API endpoint to detect programming language""" try: language = code_formatter.detect_language(code) return {"language": language, "success": True} except Exception as e: return {"success": False, "error": str(e)} @router.post("/code/format/batch") async def format_batch_endpoint(code_blocks: List[Dict]): """API endpoint to format multiple code blocks""" try: options = FormatOptions() html_output = code_formatter.format_multiple_codes(code_blocks, options) return HTMLResponse(content=html_output) except Exception as e: raise HTTPException(status_code=400, detail=f"Batch formatting error: {str(e)}") # Helper function for direct use in other modules @router.get("/code/formatter/status") async def formatter_status(): return { "module": "code_formatter", "status": "active", "version": "1.0.0", "languages": list(code_formatter._lexer_map.keys()), "themes": [theme.value for theme in CodeTheme] } app.include_router(router) print("✅ Code Formatter module registered with FastAPI") # Helper functions for easy import def format_code_html(code: str, language: str = None, theme: str = "monokai") -> str: """Format code as HTML with syntax highlighting""" options = FormatOptions(theme=CodeTheme(theme) if theme in [t.value for t in CodeTheme] else CodeTheme.MONOKAI) return code_formatter.format_code_html(code, language, options) def detect_code_language(code: str) -> str: """Detect programming language of code""" return code_formatter.detect_language(code) # Module exports __all__ = [ 'AumCoreCodeFormatter', 'CodeLanguage', 'CodeTheme', 'FormatOptions', 'code_formatter', 'format_code_html', 'detect_code_language', 'register_module' ] __version__ = "1.0.0" __author__ = "AumCore AI"