@@NAME@@
@@SIG@@
@@DESC@@
#!/usr/bin/env python3
"""gen.py — the Ludic documentation generator (v2).
Single source of truth:
docs/language/\1", s)
def split_body(body):
examples = FENCE.findall(body)
body = FENCE.sub("", body)
# pull out a "Parameters:" block
params, keep = [], []
lines = body.split("\n")
i, n = 0, len(lines)
while i < n:
if lines[i].strip().lower().startswith("parameters:"):
i += 1
while i < n and lines[i].strip():
m = PARAM.match(lines[i].strip())
if m:
params.append({"name": m.group(1), "desc": codeify(m.group(2).strip())})
i += 1
else:
keep.append(lines[i]); i += 1
desc = "\n".join(keep).strip()
paras = [codeify(p.strip()) for p in re.split(r"\n\s*\n", desc) if p.strip()]
return "
".join(paras), examples, params def load_sections(): sections = [] for cat in sorted(os.listdir(LANG)): cdir = os.path.join(LANG, cat) if not os.path.isdir(cdir): continue smeta, sblurb = {}, "" sp = os.path.join(cdir, "_section.md") if os.path.exists(sp): smeta, sbody = parse_doc(sp) sblurb = codeify(sbody.strip()) entries = [] for fn in sorted(os.listdir(cdir)): if not fn.endswith(".md") or fn == "_section.md": continue meta, body = parse_doc(os.path.join(cdir, fn)) desc, examples, params = split_body(body) meta["desc_html"] = desc meta["examples"] = examples meta["params"] = params meta["tokens_list"] = meta.get("tokens", "").split() meta["related_list"] = meta.get("related", "").split() entries.append(meta) entries.sort(key=lambda e: (int(e.get("order", 999)), e.get("name", ""))) sections.append({"id": smeta.get("id", cat), "title": smeta.get("title", cat.title()), "order": int(smeta.get("order", 999)), "blurb": sblurb, "cat": cat, "entries": entries}) sections.sort(key=lambda s: (s["order"], s["title"])) return sections # --------------------------------------------------------------------------- # symbol model for the highlighter + search + cards # --------------------------------------------------------------------------- def ns_page(nsname): return "ns-" + nsname.lower() def build_symbols(sections, palette): sym = {"keywords": {}, "types": {}, "phases": {}, "builtins": {}, "nsmethods": {}, "annotations": {}, "namespaces": {}, "tips": {}, "cards": {}, "colors_page": "ns-color"} items = {} # id -> full record for search for s in sections: for e in s["entries"]: eid = e["id"]; kind = e.get("kind", ""); tip = e.get("tip", "") page = eid + ".html" items[eid] = {"id": eid, "name": e.get("name", ""), "sig": e.get("sig", ""), "kind": kind, "category": s["id"], "section": s["title"], "tip": tip, "page": page} sym["cards"][eid] = {"name": e.get("name",""), "sig": e.get("sig",""), "tip": tip, "kind": kind, "page": page, "section": s["title"]} for tok in e["tokens_list"]: if kind == "keyword": sym["keywords"][tok] = eid elif kind == "type": sym["types"][tok] = eid elif kind == "phase": sym["phases"][tok] = eid elif kind == "builtin": sym["builtins"][tok] = {"id": eid, "params": [p["name"] for p in e["params"]]} elif kind == "namespace-method": sym["nsmethods"][tok] = {"id": eid, "params": [p["name"] for p in e["params"]]} elif kind == "annotation": sym["annotations"][tok] = eid if tip: sym["tips"][tok] = tip # namespaces: Screen/Input/Random/Map from ns methods, plus Color nsnames = set() for tok in sym["nsmethods"]: if "." in tok: nsnames.add(tok.split(".", 1)[0]) nsnames.add("Color") for nn in sorted(nsnames): sym["namespaces"][nn] = ns_page(nn) sym["cards"][ns_page(nn)] = {"name": nn, "sig": nn + ".*", "kind": "namespace", "tip": NS_TIP.get(nn, ""), "page": ns_page(nn) + ".html", "section": "Namespaces"} return sym, items NS_TIP = {"Screen": "The 2D drawing surface.", "Color": "The named color palette.", "Input": "Reading the keyboard.", "Random": "The seeded, deterministic RNG.", "Map": "The character-grid tilemap."} # --------------------------------------------------------------------------- # shared chrome # --------------------------------------------------------------------------- def nav_html(cfg, active=None): out = [] for n in cfg["nav_links"]: cls = 'class="nav-cta" ' if n.get("href") == "api.html" else "" out.append('%s' % (cls, n["href"], esc(n["label"]))) return "".join(out) def head_html(title, desc, css_file): css = open(os.path.join(ASSETS, css_file)).read() return fill("""
%s'
'%s%s' % esc(code) for code in e["examples"]) return '
@@SIG@@
@@DESC@@