1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages
DocForge2/tools/check_web_assets.py

176 lines
5 KiB
Python
Raw Permalink Normal View History

2026-07-24 22:36:44 -04:00
"""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
2026-07-29 11:37:33 -04:00
from docforge.graph_projection import (
GraphViewRequestV1,
build_graph_projection_package,
build_graph_view_plan,
)
2026-07-24 22:36:44 -04:00
from docforge.index import ProjectIndex
from docforge.project import Project
from docforge.rendering import RenderService
2026-07-29 11:37:33 -04:00
from docforge_renderers.graph import (
PORTABLE_GRAPH_CSS,
PORTABLE_GRAPH_JAVASCRIPT,
PortableGraphHtmlRenderer,
)
2026-07-24 22:36:44 -04:00
ROOT = Path(__file__).resolve().parents[1]
ASSET_ROOT = ROOT / "src" / "docforge" / "assets"
2026-07-24 22:36:44 -04:00
def _graph_browser_html() -> str:
return (ASSET_ROOT / "graph.html").read_text(encoding="utf-8")
2026-07-24 22:36:44 -04:00
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")
2026-07-29 11:37:33 -04:00
def _portable_graph_html() -> str:
project = Project.open(ROOT / "tests" / "fixtures" / "alpha")
plan = build_graph_view_plan(
project.load(),
GraphViewRequestV1(
view_id="web-quality",
title="Portable graph quality fixture",
root_node_id="guide.workflow",
depth=2,
max_nodes=20,
max_edges=40,
max_work=1_000,
),
False,
)
package = build_graph_projection_package(
plan,
renderer_id=PortableGraphHtmlRenderer.renderer_id,
renderer_version=PortableGraphHtmlRenderer.renderer_version,
max_output_bytes=1_000_000,
)
return PortableGraphHtmlRenderer().render(package).artifacts[0].content.decode("utf-8")
2026-07-24 22:36:44 -04:00
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(),
),
2026-07-29 11:37:33 -04:00
(
"portable graph HTML",
[
_tool("html-validate"),
"--stdin",
"--stdin-filename=portable-graph.html",
"--max-warnings=0",
],
_portable_graph_html(),
),
2026-07-24 22:36:44 -04:00
(
"CSS",
[
_tool("stylelint"),
"--stdin",
"--stdin-filename=graph-browser.css",
"--max-warnings=0",
],
(ASSET_ROOT / "graph.css").read_text(encoding="utf-8"),
2026-07-24 22:36:44 -04:00
),
(
"JavaScript",
[
_tool("eslint"),
"--stdin",
"--stdin-filename=graph-browser.js",
"--max-warnings=0",
],
(ASSET_ROOT / "graph.js").read_text(encoding="utf-8"),
2026-07-24 22:36:44 -04:00
),
2026-07-29 11:37:33 -04:00
(
"portable graph CSS",
[
_tool("stylelint"),
"--stdin",
"--stdin-filename=portable-graph.css",
"--max-warnings=0",
],
PORTABLE_GRAPH_CSS,
),
(
"portable graph JavaScript",
[
_tool("eslint"),
"--stdin",
"--stdin-filename=portable-graph.js",
"--max-warnings=0",
],
PORTABLE_GRAPH_JAVASCRIPT,
),
2026-07-24 22:36:44 -04:00
)
results = [_run(label, command, content) for label, command, content in checks]
return 0 if all(results) else 1
if __name__ == "__main__":
sys.exit(main())