#!/usr/bin/env python3 # /// script # requires-python = ">=3.11" # dependencies = ["pyyaml>=6"] # /// """Render an Open Knowledge Format (OKF) bundle as a single self-contained, interactive HTML graph (`viz.html`). No backend, no install on the viewing side, no data leaves the page — concepts become nodes (coloured by `type`, sized by body length), markdown links and bundle-internal `sources` become edges, and clicking a node opens a wiki-style panel with its rendered markdown, OKF v0.2 provenance/trust/lifecycle metadata, outgoing links, and "Cited by" backlinks. Features: force/concentric/breadth-first/circle/grid layouts, per-type filter, free-text search, neighbour highlight, clickable cross-links and backlinks. The default layout is force (cose) up to AUTO_COSE_MAX concepts, then the linear concentric layout — force-directed cost grows roughly quadratically with node count and freezes the page on large bundles. An explicit --layout always wins. Run: uv run okf_visualize.py [-o viz.html] """ from __future__ import annotations import argparse import json import re import sys from pathlib import Path import yaml RESERVED = {"index.md", "log.md"} # Force (cose) layout froze the page for ~32 s at ~2k concepts (measured in # Chrome); the linear layouts load the same bundle in under 2 s. Past this size # the default switches to concentric, and the in-page layout picker asks before # running force. An explicit --layout (or ?layout=) still wins. AUTO_COSE_MAX = 1000 # Above this the page is slow on any layout (23k concepts measured: ~27 s load, # ~650 MB heap) and reads as a hairball — warn and suggest rendering a subtree. SCALE_WARN = 5000 FENCE = re.compile(r"^(```|~~~)") LINK = re.compile(r"(? str: """JSON-encode ``obj`` for safe embedding inside an inline ```` in a concept body ends the inline script early (truncating the embedded ``NODES``/``EDGES`` and breaking the whole page), and ``