This commit is contained in:
232
.code_doc_cli/generators/markdown_generator.py
Normal file
232
.code_doc_cli/generators/markdown_generator.py
Normal file
@@ -0,0 +1,232 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user