Files
code-doc-cli/.code_doc_cli/generators/markdown_generator.py
7000pctAUTO 0cf1329e95
Some checks failed
CI / test (push) Has been cancelled
Add generators and parsers modules
2026-01-29 16:51:52 +00:00

233 lines
7.7 KiB
Python

"""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)