{name}
{summary}
{path}
from __future__ import annotations
import html
import json
from collections import defaultdict
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parent.parent
CATALOG_MD = ROOT / "docs" / "CapabilityCatalog.md"
CATALOG_HTML_DIR = ROOT / "docs" / "catalog"
CATALOG_HTML = CATALOG_HTML_DIR / "index.html"
CATALOG_JSON = CATALOG_HTML_DIR / "registry.json"
CATALOG_SEARCH = CATALOG_HTML_DIR / "search.html"
GRAPH_HTML = ROOT / "docs" / "graph" / "index.html"
def _grouped_capabilities(
indexed_entries: list[tuple[dict[str, Any], dict[str, Any]]],
) -> dict[str, list[tuple[dict[str, Any], dict[str, Any]]]]:
grouped: dict[str, list[tuple[dict[str, Any], dict[str, Any]]]] = defaultdict(
list
)
for index_item, entry in indexed_entries:
domain = index_item.get("domain", "unknown")
grouped[domain].append((index_item, entry))
return dict(sorted(grouped.items()))
def render_markdown(
index: dict[str, Any],
indexed_entries: list[tuple[dict[str, Any], dict[str, Any]]],
) -> str:
lines = [
"# Capability Catalog",
"",
f"**Domain:** {index.get('domain', 'unknown')} ",
f"**Updated:** {index.get('updated', 'unknown')} ",
f"**Entries:** {len(indexed_entries)}",
"",
"Generated by `reuse-surface catalog`. Do not edit manually.",
"",
]
for domain, items in _grouped_capabilities(indexed_entries).items():
lines.extend([f"## {domain}", ""])
for index_item, entry in sorted(items, key=lambda pair: pair[0]["id"]):
lines.extend(
[
f"### {index_item['name']}",
"",
f"- **ID:** `{index_item['id']}`",
f"- **Vector:** {index_item['vector']}",
f"- **Owner:** {index_item.get('owner', 'unknown')}",
f"- **Path:** `{index_item['path']}`",
f"- **Summary:** {index_item['summary']}",
"",
]
)
guidance = entry.get("consumer_guidance") or {}
limitations = guidance.get("known_limitations") or []
if limitations:
lines.append("**Known limitations:**")
lines.extend(f"- {item}" for item in limitations)
lines.append("")
return "\n".join(lines).rstrip() + "\n"
def render_html(
index: dict[str, Any],
indexed_entries: list[tuple[dict[str, Any], dict[str, Any]]],
) -> str:
sections: list[str] = []
for domain, items in _grouped_capabilities(indexed_entries).items():
cards: list[str] = []
for index_item, entry in sorted(items, key=lambda pair: pair[0]["id"]):
name = html.escape(index_item["name"])
summary = html.escape(index_item["summary"])
cap_id = html.escape(index_item["id"])
vector = html.escape(index_item["vector"])
path = html.escape(index_item["path"])
cards.append(
f""" {summary} {path}{name}
{html.escape(domain)}
\n" + "\n".join(cards) + "
Updated {html.escape(str(index.get('updated', 'unknown')))} · {len(indexed_entries)} entries
{body} """ def render_search_html() -> str: return """Client-side search over registry.json. Generated by reuse-surface catalog.
Generated from entry relations fields. Regenerate with reuse-surface graph.