diff --git a/gen_viz.py b/gen_viz.py new file mode 100644 index 0000000..df4e153 --- /dev/null +++ b/gen_viz.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +"""Generuje viz.html (graph viewer) dla tego bundle'a. + +Viewer z GoogleCloudPlatform/knowledge-catalog jest samowystarczalny: cały +bundle jest wpiekany do pliku HTML jako `window.BUNDLE` (nodes/edges/bodies). +Nie czyta plików .md w runtime, więc nie potrzebuje manifestu ani serwera — +źródłem danych jest ten skrypt, uruchamiany po każdej zmianie bundle'a. + +Logika viewera (templates/viz.html, static/viz.js, static/viz.css) jest +wstawiana dosłownie, bez zmian. Skrypt koryguje wyłącznie warstwę zbierania +danych, w dwóch punktach, w których upstreamowy generator rozmija się ze +specyfikacją OKF: + +1. `_extract_links` pomija linki bundle-relative zaczynające się od `/` + (generator.py:74), czyli dokładnie formę zalecaną przez §5.1. Bundle + trzymający się zalecenia dostaje graf bez krawędzi. Sam viewer te linki + rozumie — viz.js:297 rozwiązuje `/...md` na węzeł — więc dokładamy je do + ekstrakcji krawędzi. +2. `_walk_concepts` pomija tylko `index.md`, przez co zarezerwowany `log.md` + ląduje w grafie jako koncept typu "Unknown". Wg §3.1 zarezerwowane nazwy + nie są konceptami. + +Wymaga: PyYAML oraz repozytorium knowledge-catalog (domyślnie +/tmp/knowledge-catalog — nadpisz zmienną KNOWLEDGE_CATALOG). + +Uruchomienie: python3 gen_viz.py +""" + +from __future__ import annotations + +import os +import sys +from pathlib import Path + +BUNDLE_ROOT = Path(__file__).resolve().parent +BUNDLE_NAME = "Ski 2027 — Skicircus Saalbach" +CATALOG = Path(os.environ.get("KNOWLEDGE_CATALOG", "/tmp/knowledge-catalog")) + +sys.path.insert(0, str(CATALOG / "okf" / "src")) + +try: + from reference_agent.viewer import generator as G +except ModuleNotFoundError as exc: # pragma: no cover + sys.exit( + f"Nie znaleziono viewera ({exc}).\n" + f"Sklonuj: git clone https://github.com/GoogleCloudPlatform/" + f"knowledge-catalog {CATALOG}" + ) + +RESERVED = {"index.md", "log.md"} + +_upstream_extract_links = G._extract_links +_upstream_walk_concepts = G._walk_concepts + + +def _extract_links(body: str, doc_dir: Path, bundle_root: Path) -> list[str]: + """Upstream + linki bundle-relative (§5.1), które upstream odrzuca.""" + out = _upstream_extract_links(body, doc_dir, bundle_root) + seen = set(out) + for match in G._LINK_RE.finditer(body): + target = match.group(1) + if "://" in target or not target.startswith("/"): + continue + rel = target[1:] + if rel.endswith(".md"): + rel = rel[:-3] + if rel and rel not in seen: + seen.add(rel) + out.append(rel) + return out + + +def _walk_concepts(bundle_root: Path): + """Upstream, ale bez plików zarezerwowanych (§3.1).""" + return [ + c + for c in _upstream_walk_concepts(bundle_root) + if f"{c.id}.md".rsplit("/", 1)[-1] not in RESERVED + ] + + +G._extract_links = _extract_links +G._walk_concepts = _walk_concepts + + +def main() -> int: + out_path = BUNDLE_ROOT / "viz.html" + stats = G.generate_visualization( + BUNDLE_ROOT, out_path, bundle_name=BUNDLE_NAME + ) + print(f"Zapisano {out_path}") + print( + f" koncepty: {stats['concepts']}, krawędzie: {stats['edges']}, " + f"rozmiar: {stats['bytes'] / 1024:.1f} KiB" + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/viz.html b/viz.html new file mode 100644 index 0000000..badd501 --- /dev/null +++ b/viz.html @@ -0,0 +1,555 @@ + + + + +OKF Bundle Viewer + + + + + +
+
+ + OKF bundle +
+
+ + + + +
+
+ +
+
+
+
Click a node to see its details.
+ +
+
+ + + + +