1"""Docs viewer + source viewer endpoints. 2 3Split out of api.py — these have no shared state with the rest of the 4dashboard, just a few rendering helpers in ``maf.dashboard.docs_render``. 5""" 6 7from __future__ import annotations 8 9from pathlib import Path 10 11from fastapi import APIRouter, HTTPException, Request, Response 12from fastapi.responses import HTMLResponse 13from fastapi.templating import Jinja2Templates 14 15router = APIRouter() 16 17# Templates live in the same directory as the dashboard app's templates. 18_TEMPLATES_DIR = Path(__file__).resolve().parents[1] / "templates" 19templates = Jinja2Templates(directory=str(_TEMPLATES_DIR)) 20 21 22@router.get("/docs", response_class=HTMLResponse) 23async def page_docs_index(request: Request) -> HTMLResponse: 24 """Docs hub — links into manual / architecture / api / runbook etc. 25 26 Every described function in those docs links to the underlying source 27 file via ``/source/{path}?line={N}`` so users can confirm the described 28 behavior actually exists in the code. 29 """ 30 from maf.dashboard.docs_render import list_docs 31 32 return templates.TemplateResponse("docs_index.html", { 33 "request": request, 34 "active_nav": "docs", 35 "docs": list_docs(), 36 }) 37 38 39@router.get("/docs/{slug}", response_class=HTMLResponse) 40async def page_doc(request: Request, slug: str) -> HTMLResponse: 41 """Render one markdown doc with JSON-as-readable-table prettification 42 and src: link rewriting.""" 43 from maf.dashboard.docs_render import render_doc 44 45 rendered = render_doc(slug) 46 if rendered is None: 47 raise HTTPException(404, f"Doc {slug!r} not found") 48 return templates.TemplateResponse("doc.html", { 49 "request": request, 50 "active_nav": "docs", 51 "doc": rendered, 52 }) 53 54 55@router.get("/source/{rel_path:path}", response_class=HTMLResponse) 56async def page_source(request: Request, rel_path: str, line: int | None = None) -> HTMLResponse: 57 """Source-code viewer with line numbers + optional highlight.""" 58 from maf.dashboard.docs_render import render_source 59 60 rendered = render_source(rel_path, highlight_line=line) 61 if rendered is None: 62 raise HTTPException(404, f"Source {rel_path!r} not found or not viewable") 63 return templates.TemplateResponse("source.html", { 64 "request": request, 65 "active_nav": "docs", 66 "src": rendered, 67 }) 68 69 70@router.get("/docs.css") 71async def docs_css() -> Response: 72 """Pygments stylesheet for code highlighting in docs + source viewer.""" 73 from maf.dashboard.docs_render import pygments_css 74 75 return Response(content=pygments_css(), media_type="text/css")