diff --git a/.code_doc_cli/generators/templates.py b/.code_doc_cli/generators/templates.py new file mode 100644 index 0000000..ec56a33 --- /dev/null +++ b/.code_doc_cli/generators/templates.py @@ -0,0 +1,243 @@ +"""Documentation templates.""" + +from typing import Optional +from pygments.formatters import HtmlFormatter +from pygments import highlight +from pygments.lexers import get_lexer_by_name +from pygments.styles import get_style_by_name + + +class DocumentationTemplate: + """Template for documentation output.""" + + def __init__(self, style: str = "default", theme: str = "default"): + self.style = style + self.theme = theme + + def format_function( + self, + name: str, + description: str, + parameters: list[tuple], + return_type: Optional[str], + return_description: Optional[str], + raises: list[tuple], + examples: list[str], + source_file: str, + line_number: int, + decorators: list[str], + ) -> str: + """Format function documentation.""" + lines = [f"### {name}", ""] + + if decorators: + for dec in decorators: + lines.append(f"```python\n{dec}\n```\n") + + if description: + lines.append(f"{description}\n") + + if parameters: + lines.append("**Parameters:**\n") + lines.append("| Name | Type | Default | Description |") + lines.append("|------|------|---------|-------------|") + for param in parameters: + if len(param) >= 4: + param_name, param_type, default, param_desc = param[:4] + else: + param_name = param[0] if len(param) > 0 else "" + param_type = param[1] if len(param) > 1 else None + default = param[2] if len(param) > 2 else None + param_desc = param[3] if len(param) > 3 else None + default_str = f"`{default}`" if default else "-" + desc_str = param_desc or "-" + type_str = f"`{param_type}`" if param_type else "-" + lines.append(f"| {param_name} | {type_str} | {default_str} | {desc_str} |") + lines.append("") + + if return_type or return_description: + lines.append("**Returns:**\n") + if return_type: + lines.append(f"- Type: `{return_type}`") + if return_description: + lines.append(f"\n{return_description}") + lines.append("") + + if raises: + lines.append("**Raises:**\n") + for exc_type, exc_desc in raises: + lines.append(f"- `{exc_type}`: {exc_desc}") + lines.append("") + + if examples: + lines.append("**Examples:**\n") + for example in examples: + lines.append(f"```python\n{example}\n```\n") + + lines.append(f"*Source: {source_file}:{line_number}*") + + return "\n".join(lines) + + def format_class( + self, + name: str, + description: str, + attributes: list[tuple], + methods: list[str], + parameters: list[tuple], + decorators: list[str], + source_file: str, + line_number: int, + ) -> str: + """Format class documentation.""" + lines = [f"## {name}", ""] + + if decorators: + for dec in decorators: + lines.append(f"```python\n{dec}\n```\n") + + if description: + lines.append(f"{description}\n") + + if parameters: + lines.append("**Inherits:**\n") + for param in parameters: + if isinstance(param, tuple) and len(param) >= 2: + base_name, base_desc = param[0], param[1] + else: + base_name, base_desc = str(param), "" + lines.append(f"- {base_name}: {base_desc or ''}") + lines.append("") + + if attributes: + lines.append("**Attributes:**\n") + lines.append("| Name | Type | Description |") + lines.append("|------|------|-------------|") + for attr in attributes: + if len(attr) >= 3: + attr_name, attr_type, attr_desc = attr[:3] + else: + attr_name = attr[0] if len(attr) > 0 else "" + attr_type = attr[1] if len(attr) > 1 else None + attr_desc = attr[2] if len(attr) > 2 else None + type_str = f"`{attr_type}`" if attr_type else "-" + desc_str = attr_desc or "-" + lines.append(f"| {attr_name} | {type_str} | {desc_str} |") + lines.append("") + + if methods: + lines.append("**Methods:**\n") + for method in methods: + lines.append(f"- {method}") + lines.append("") + + lines.append(f"*Source: {source_file}:{line_number}*") + + return "\n".join(lines) + + def format_module( + self, + name: str, + description: str, + imports: list[str], + elements_count: dict, + ) -> str: + """Format module documentation.""" + lines = [f"# {name}", ""] + + if description: + lines.append(f"{description}\n") + + lines.append("## Summary") + if elements_count: + summary_parts = [] + if elements_count.get("functions"): + summary_parts.append(f"{elements_count['functions']} functions") + if elements_count.get("classes"): + summary_parts.append(f"{elements_count['classes']} classes") + if elements_count.get("constants"): + summary_parts.append(f"{elements_count['constants']} constants") + if summary_parts: + lines.append(f"This module contains {', '.join(summary_parts)}.") + lines.append("") + + if imports: + lines.append("## Imports") + for imp in imports[:10]: + lines.append(f"- `{imp}`") + if len(imports) > 10: + lines.append(f"- ... and {len(imports) - 10} more") + lines.append("") + + return "\n".join(lines) + + def format_interface( + self, + name: str, + description: str, + properties: list[tuple], + ) -> str: + """Format interface documentation.""" + lines = [f"## {name}", ""] + + if description: + lines.append(f"{description}\n") + + if properties: + lines.append("**Properties:**\n") + lines.append("| Name | Type | Description |") + lines.append("|------|------|-------------|") + for prop in properties: + if len(prop) >= 3: + prop_name, prop_type, prop_desc = prop[:3] + else: + prop_name = prop[0] if len(prop) > 0 else "" + prop_type = prop[1] if len(prop) > 1 else None + prop_desc = prop[2] if len(prop) > 2 else None + type_str = f"`{prop_type}`" if prop_type else "-" + desc_str = prop_desc or "-" + lines.append(f"| {prop_name} | {type_str} | {desc_str} |") + lines.append("") + + return "\n".join(lines) + + +class SyntaxHighlighter: + """Syntax highlighting utilities.""" + + THEMES = { + "default": "default", + "dark": "monokai", + "light": "manni", + "colorful": "rainbow_dash", + } + + def __init__(self, theme: str = "default"): + self.theme = self.THEMES.get(theme, "default") + self.style = get_style_by_name(self.theme) + self.formatter = HtmlFormatter( + style=self.style, + linenos=True, + cssclass="code-highlight", + noclasses=False, + ) + + def highlight(self, code: str, language: str) -> str: + """Highlight code with syntax highlighting. + + Args: + code: Code to highlight + language: Programming language + + Returns: + HTML formatted highlighted code + """ + try: + lexer = get_lexer_by_name(language) + return highlight(code, lexer, self.formatter) + except Exception: + return f"
{code}"
+
+ def get_css(self) -> str:
+ """Get CSS for syntax highlighting."""
+ return self.formatter.get_style_defs()