"""Validate the exact embedded graph-browser HTML, CSS, and JavaScript."""
from __future__ import annotations
import os
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path
from typing import cast
from docforge.index import ProjectIndex
from docforge.project import Project
from docforge.rendering import RenderService
ROOT = Path(__file__).resolve().parents[1]
ASSET_ROOT = ROOT / "src" / "docforge" / "assets"
def _graph_browser_html() -> str:
return (ASSET_ROOT / "graph.html").read_text(encoding="utf-8")
def _rendered_manual_html() -> str:
with tempfile.TemporaryDirectory() as directory:
fixture = ROOT / "tests" / "fixtures" / "alpha"
project_root = Path(directory) / "alpha"
shutil.copytree(fixture, project_root)
project = Project.open(project_root)
ProjectIndex(project).build()
result = RenderService(project).render("manual")
output = result.get("output")
if not isinstance(output, dict):
raise RuntimeError("Manual render did not return output identity")
relative_path = cast(dict[str, object], output).get("path")
if not isinstance(relative_path, str):
raise RuntimeError("Manual render did not return an output path")
return (project_root / relative_path).read_text(encoding="utf-8")
def _tool(name: str) -> str:
suffix = ".cmd" if os.name == "nt" else ""
path = ROOT / "node_modules" / ".bin" / f"{name}{suffix}"
if not path.is_file():
raise RuntimeError(f"Missing web validator {name}; run npm ci")
return str(path)
def _run(label: str, command: list[str], content: str) -> bool:
print(f"Checking {label}...")
result = subprocess.run(
command,
cwd=ROOT,
input=content,
text=True,
check=False,
)
return result.returncode == 0
def main() -> int:
html = _graph_browser_html()
checks = (
(
"HTML",
[
_tool("html-validate"),
"--stdin",
"--stdin-filename=graph-browser.html",
"--max-warnings=0",
],
html,
),
(
"rendered manual HTML",
[
_tool("html-validate"),
"--stdin",
"--stdin-filename=rendered-manual.html",
"--max-warnings=0",
],
_rendered_manual_html(),
),
(
"CSS",
[
_tool("stylelint"),
"--stdin",
"--stdin-filename=graph-browser.css",
"--max-warnings=0",
],
(ASSET_ROOT / "graph.css").read_text(encoding="utf-8"),
),
(
"JavaScript",
[
_tool("eslint"),
"--stdin",
"--stdin-filename=graph-browser.js",
"--max-warnings=0",
],
(ASSET_ROOT / "graph.js").read_text(encoding="utf-8"),
),
)
results = [_run(label, command, content) for label, command, content in checks]
return 0 if all(results) else 1
if __name__ == "__main__":
sys.exit(main())