This commit is contained in:
@@ -1,70 +1,71 @@
|
||||
"""Generator for documentation output."""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from .parser import parse_openapi_spec, load_spec_file
|
||||
from .models import Endpoint, APISpec
|
||||
from typing import Any, Optional
|
||||
|
||||
from src.core.models import OpenAPISpec
|
||||
from src.core.parser import _basic_validate, parse_openapi_spec
|
||||
|
||||
|
||||
def generate_docs(spec_file: str, output: str = None, format: str = 'html', open_browser: bool = False):
|
||||
"""Generate documentation in the specified format.
|
||||
def generate_docs(
|
||||
spec_source: str | Path | dict[str, Any],
|
||||
format: str = "html",
|
||||
output_path: Optional[str] = None,
|
||||
template_path: Optional[str] = None,
|
||||
) -> str:
|
||||
if isinstance(spec_source, dict):
|
||||
spec_data = spec_source
|
||||
elif isinstance(spec_source, (str, Path)):
|
||||
spec_path = Path(spec_source)
|
||||
if spec_path.exists():
|
||||
content = spec_path.read_text()
|
||||
if spec_path.suffix in [".yaml", ".yml"]:
|
||||
import yaml
|
||||
|
||||
Args:
|
||||
spec_file: Path to the OpenAPI spec file
|
||||
output: Output file path or directory
|
||||
format: Output format (html, markdown, json, all)
|
||||
open_browser: Whether to open the generated file in browser
|
||||
"""
|
||||
result = parse_openapi_spec(spec_file)
|
||||
spec_data = yaml.safe_load(content)
|
||||
else:
|
||||
spec_data = json.loads(content)
|
||||
else:
|
||||
raise FileNotFoundError(f"Spec file not found: {spec_source}")
|
||||
else:
|
||||
raise ValueError(f"Invalid spec source type: {type(spec_source)}")
|
||||
|
||||
if not result.get('valid'):
|
||||
raise ValueError(f"Invalid spec: {result.get('errors')}")
|
||||
is_valid, errors = _basic_validate(spec_data)
|
||||
if not is_valid:
|
||||
raise ValueError(f"Invalid spec: {errors}")
|
||||
|
||||
spec = result['spec']
|
||||
|
||||
if format == 'all':
|
||||
for fmt in ['html', 'markdown', 'json']:
|
||||
generate_docs(spec_file, output, fmt, open_browser and fmt == 'html')
|
||||
return
|
||||
|
||||
if not output:
|
||||
base_name = Path(spec_file).stem
|
||||
if format == 'html':
|
||||
output = f"{base_name}.html"
|
||||
elif format == 'markdown':
|
||||
output = f"{base_name}.md"
|
||||
elif format == 'json':
|
||||
output = f"{base_name}_docs.json"
|
||||
|
||||
if format == 'html':
|
||||
from .templates.html_template import generate_html
|
||||
generate_html(spec, output)
|
||||
elif format == 'markdown':
|
||||
from .templates.markdown_template import generate_markdown
|
||||
generate_markdown(spec, output)
|
||||
elif format == 'json':
|
||||
generate_json_docs(spec, output)
|
||||
|
||||
print(f"Generated {format} documentation: {output}")
|
||||
|
||||
if open_browser and format == 'html':
|
||||
import webbrowser
|
||||
webbrowser.open(f'file://{os.path.abspath(output)}')
|
||||
spec = parse_openapi_spec(spec_data)
|
||||
return spec
|
||||
|
||||
|
||||
def generate_json_docs(spec: dict, output: str):
|
||||
"""Generate JSON documentation."""
|
||||
from .parser import extract_endpoints
|
||||
|
||||
endpoints = extract_endpoints(spec)
|
||||
|
||||
docs = {
|
||||
'title': spec.get('info', {}).get('title', 'API Documentation'),
|
||||
'version': spec.get('info', {}).get('version', '1.0.0'),
|
||||
'description': spec.get('info', {}).get('description', ''),
|
||||
'endpoints': endpoints,
|
||||
'tags': spec.get('tags', []),
|
||||
'servers': spec.get('servers', [])
|
||||
def extract_endpoints(spec: OpenAPISpec) -> list:
|
||||
endpoints = []
|
||||
for path, path_item in spec.paths.items():
|
||||
for method, operation in path_item.model_dump().items():
|
||||
if method in ["get", "put", "post", "delete", "options", "head", "patch", "trace"]:
|
||||
if operation:
|
||||
endpoints.append(
|
||||
{
|
||||
"path": path,
|
||||
"method": method.upper(),
|
||||
"summary": operation.get("summary", ""),
|
||||
"description": operation.get("description", ""),
|
||||
"tags": operation.get("tags", []),
|
||||
}
|
||||
)
|
||||
return endpoints
|
||||
|
||||
with open(output, 'w') as f:
|
||||
json.dump(docs, f, indent=2)
|
||||
|
||||
def generate_template_context(spec: OpenAPISpec) -> dict[str, Any]:
|
||||
spec_dict = spec.model_dump()
|
||||
return {
|
||||
"spec": spec_dict,
|
||||
"info": spec_dict.get("info", {}),
|
||||
"paths": spec_dict.get("paths", {}),
|
||||
"servers": spec_dict.get("servers", []),
|
||||
"tags": spec_dict.get("tags", []),
|
||||
"components": spec_dict.get("components", {}),
|
||||
"security": spec_dict.get("security", []),
|
||||
"external_docs": spec_dict.get("externalDocs"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user