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