"""Markdown documentation generator.""" from typing import Optional from datetime import datetime from .templates import DocumentationTemplate, SyntaxHighlighter from ..parsers.base import DocElement, ElementType class MarkdownGenerator: """Generator for Markdown documentation.""" def __init__( self, template_style: str = "default", theme: str = "default", syntax_highlighting: bool = True, ): self.template = DocumentationTemplate(style=template_style) self.highlighter = SyntaxHighlighter(theme) if syntax_highlighting else None def generate( self, elements: list[DocElement], title: Optional[str] = None, include_metadata: bool = True, ) -> str: """Generate Markdown documentation. Args: elements: List of documentation elements title: Documentation title include_metadata: Include generation metadata Returns: Markdown formatted documentation """ lines = [] if include_metadata: if title: lines.append(f"# {title}") else: lines.append("# API Documentation") lines.append("") lines.append(f"*Generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*") lines.append("") modules = [e for e in elements if e.element_type == ElementType.MODULE] classes = [e for e in elements if e.element_type == ElementType.CLASS] functions = [e for e in elements if e.element_type == ElementType.FUNCTION] methods = [e for e in elements if e.element_type == ElementType.METHOD] interfaces = [e for e in elements if e.element_type == ElementType.INTERFACE] structs = [e for e in elements if e.element_type == ElementType.STRUCT] constants = [e for e in elements if e.element_type == ElementType.CONSTANT] variables = [e for e in elements if e.element_type == ElementType.VARIABLE] if modules: lines.append("## Modules") lines.append("") for module in modules: lines.append(self._format_module(module)) lines.append("") if classes or structs: lines.append("## Classes & Structs") lines.append("") for elem in classes + structs: lines.append(self._format_class(elem)) lines.append("") if interfaces: lines.append("## Interfaces") lines.append("") for interface in interfaces: lines.append(self._format_interface(interface)) lines.append("") if functions: lines.append("## Functions") lines.append("") for func in functions: lines.append(self._format_function(func)) lines.append("") if methods: lines.append("## Methods") lines.append("") for method in methods: lines.append(self._format_function(method)) lines.append("") if constants or variables: lines.append("## Constants & Variables") lines.append("") for elem in constants + variables: lines.append(f"### {elem.name}") lines.append("") if elem.description: lines.append(f"{elem.description}") lines.append("") lines.append(f"*Source: {elem.source_file}:{elem.line_number}*") lines.append("") return "\n".join(lines) def _format_module(self, element: DocElement) -> str: """Format module documentation.""" elements_count = { "functions": sum(1 for e in element.imports if "function" in e.lower()), "classes": sum(1 for e in element.imports if "class" in e.lower()), "constants": 0, } return self.template.format_module( name=element.name, description=element.description, imports=element.imports, elements_count=elements_count, ) def _format_class(self, element: DocElement) -> str: """Format class documentation.""" params = [(p.name, p.type_hint, p.description) for p in element.parameters] method_names = [] for elem in element.imports: if "." in elem: method_names.append(elem.split(".", 1)[1]) return self.template.format_class( name=element.name, description=element.description, attributes=element.attributes, methods=method_names, parameters=params, decorators=element.decorators, source_file=element.source_file, line_number=element.line_number, ) def _format_function(self, element: DocElement) -> str: """Format function documentation.""" params = [ (p.name, p.type_hint, p.default_value, p.description) for p in element.parameters ] raises = [(r[0], r[1]) for r in element.raises] return self.template.format_function( name=element.name, description=element.description, parameters=params, return_type=element.return_type, return_description=element.return_description, raises=raises, examples=element.examples, source_file=element.source_file, line_number=element.line_number, decorators=element.decorators, ) def _format_interface(self, element: DocElement) -> str: """Format interface documentation.""" return self.template.format_interface( name=element.name, description=element.description, properties=element.attributes, ) def generate_json(self, elements: list[DocElement]) -> str: """Generate JSON output for machine-readable format. Args: elements: List of documentation elements Returns: JSON formatted string """ import json data = { "generated_at": datetime.now().isoformat(), "elements": [], } for elem in elements: elem_data = { "name": elem.name, "type": elem.element_type.value, "description": elem.description, "source_file": elem.source_file, "line_number": elem.line_number, "visibility": elem.visibility, } if elem.parameters: elem_data["parameters"] = [ { "name": p.name, "type": p.type_hint, "default": p.default_value, "description": p.description, } for p in elem.parameters ] if elem.return_type: elem_data["return"] = { "type": elem.return_type, "description": elem.return_description, } if elem.attributes: elem_data["attributes"] = [ {"name": a[0], "type": a[1], "description": a[2]} for a in elem.attributes ] if elem.raises: elem_data["raises"] = [ {"type": r[0], "description": r[1]} for r in elem.raises ] if elem.examples: elem_data["examples"] = elem.examples if elem.decorators: elem_data["decorators"] = elem.decorators data["elements"].append(elem_data) return json.dumps(data, indent=2)