From 73998020b3ea712d4a48fac633d6330339a20d13 Mon Sep 17 00:00:00 2001 From: buenosairesam Date: Tue, 22 Sep 2026 05:45:52 -0300 Subject: [PATCH] docgen graphgen ui and converging update --- soleprint/atlas2/docgen/Makefile | 10 +- soleprint/atlas2/docgen/README.md | 4 +- soleprint/atlas2/docgen/book/__init__.py | 16 +- soleprint/atlas2/docgen/book/build.py | 20 +- soleprint/atlas2/docgen/book/checks.py | 12 +- soleprint/atlas2/docgen/book/config.py | 12 +- soleprint/atlas2/docgen/book/document.py | 32 +- soleprint/atlas2/docgen/cli/emit.py | 20 +- .../atlas2/docgen/docgen.project.example.toml | 4 +- .../atlas2/docgen/docs/img/architecture.svg | 798 ++++++++-------- soleprint/atlas2/docgen/docs/img/minimap.svg | 883 +++++++++--------- soleprint/atlas2/docgen/docs/index.html | 52 +- soleprint/atlas2/docgen/docs/models.md | 18 +- soleprint/atlas2/docgen/emitters/auto.py | 4 +- soleprint/atlas2/docgen/emitters/dot.py | 4 +- soleprint/atlas2/docgen/emitters/markdown.py | 4 +- .../{docsite.py => minisite/__init__.py} | 32 +- .../emitters/{site.py => minisite/onepage.py} | 16 +- soleprint/atlas2/docgen/emitters/paged.py | 8 +- soleprint/atlas2/docgen/ops/pages.py | 6 +- soleprint/atlas2/docgen/selftest.py | 64 +- soleprint/atlas2/docgen/viewer_test.js | 2 +- 22 files changed, 1019 insertions(+), 1002 deletions(-) rename soleprint/atlas2/docgen/emitters/{docsite.py => minisite/__init__.py} (91%) rename soleprint/atlas2/docgen/emitters/{site.py => minisite/onepage.py} (98%) diff --git a/soleprint/atlas2/docgen/Makefile b/soleprint/atlas2/docgen/Makefile index d963bac..24fa88c 100644 --- a/soleprint/atlas2/docgen/Makefile +++ b/soleprint/atlas2/docgen/Makefile @@ -55,7 +55,7 @@ SLUG_ARG := $(if $(SLUG),--slug $(SLUG)) OVER_ARG := $(if $(OVERLAY),--overlay $(OVERLAY)) ONLY_ARGS := $(foreach n,$(subst $(comma), ,$(ONLY)),--only $(n)) -.PHONY: help sync lock book run scaffold check ir db code view graph index site minimap explore docs self doctor clean +.PHONY: help sync lock book run scaffold check ir db code view graph index minisite minimap explore docs self doctor clean help: ## List every target @echo "docgen — static analysis of a tree, and the artifacts that fall out of it" @@ -130,9 +130,9 @@ index: ## OUT/ir.json -> OUT/index.md and OUT/sidebar.json @$(CLI) emit index $(OUT)/ir.json -o $(OUT)/index.md @$(CLI) emit index $(OUT)/ir.json -o $(OUT)/sidebar.json -site: view ## OUT/view.json -> a self-contained docs site in OUT/site - @$(CLI) emit site $(OUT)/view.json -o $(OUT)/site $(STYLE_ARGS) - @echo " open $(OUT)/site/index.html" +minisite: view ## OUT/view.json -> a self-contained page in OUT/minisite + @$(CLI) emit minisite $(OUT)/view.json -o $(OUT)/minisite $(STYLE_ARGS) + @echo " open $(OUT)/minisite/index.html" minimap: ## OUT/ir.json -> OUT/minimap.svg — what is where, read from the colours @$(CLI) emit minimap $(OUT)/ir.json -o $(OUT)/minimap.svg $(STYLE_ARGS) --scale $(SCALE) @@ -149,7 +149,7 @@ docs: ## Regenerate the figures in docs/ — docgen documented by docgen @$(CLI) emit minimap /tmp/$(PKG)-docs.json -o $(HERE)/docs/img/minimap.svg --scale 0.5 --width 860 @$(CLI) emit erd $(OUT)/ir.json -o $(HERE)/docs/img/erd.svg 2>/dev/null \ || echo " (erd figure kept — needs a schema IR at $(OUT)/ir.json to refresh)" - @PYTHONPATH=$(PARENT) $(PY) -c "from $(PKG).emitters.site import VIEWER, _slots, _fill; \ + @PYTHONPATH=$(PARENT) $(PY) -c "from $(PKG).emitters.minisite import VIEWER, _slots, _fill; \ from $(PKG).style import Style; import pathlib; \ pathlib.Path('$(HERE)/docs/viewer.html').write_text( \ _fill(VIEWER.replace('__TITLE__', 'docgen docs'), _slots(Style.load('lucid'))))" diff --git a/soleprint/atlas2/docgen/README.md b/soleprint/atlas2/docgen/README.md index b02ddf8..f44859a 100644 --- a/soleprint/atlas2/docgen/README.md +++ b/soleprint/atlas2/docgen/README.md @@ -102,7 +102,7 @@ output made of all of them. Keys docgen deliberately doesn't do (`[extract.db] u shell/YAML/SQL `ext`, unknown readers) are refused with what to do instead. A book's diagram is split into **pages** by structure — overview first, one page per -subsystem — measured until each fits its column. On the site the diagrams are inline, +subsystem — measured until each fits its column. On the minisite the diagrams are inline, so a box opens its page; in a notebook, a page index links every figure, and each figure is an SVG cell attachment that renders without running anything. @@ -282,7 +282,7 @@ about either. ## Testing ```bash -make check # docgen's own suite: 346 after make sync, 331 with nothing +make check # docgen's own suite: 348 after make sync, 333 with nothing make check BOOK=out/book/x # one book's own level — or a project's .docgen/ make doctor # the machine; never fails ``` diff --git a/soleprint/atlas2/docgen/book/__init__.py b/soleprint/atlas2/docgen/book/__init__.py index f5fea7e..856c4ab 100644 --- a/soleprint/atlas2/docgen/book/__init__.py +++ b/soleprint/atlas2/docgen/book/__init__.py @@ -30,7 +30,7 @@ artifacts useful, and that property is the whole reason the sequence is worth having. **Not a new pipeline.** Everything here composes functions that already existed -— `ops.overview`, `emitters.dot`, `emitters.site`, `notebook.spec`. The spine +— `ops.overview`, `emitters.dot`, `emitters.minisite`, `notebook.spec`. The spine adds a ledger and two measurements. If it ever starts doing the work itself, something has gone wrong. @@ -48,7 +48,7 @@ from pathlib import Path from .larder import Larder -# The two spine steps. Named here because the notebook, the site and the checks +# The two spine steps. Named here because the notebook, the minisite and the checks # all have to agree on what they are called, and three string literals in three # files is how they stop agreeing. FIRST = "larder" @@ -258,13 +258,13 @@ class Book: # -- writing ---------------------------------------------------------- - def close(self, *, site=None) -> Step: + def close(self, *, minisite=None) -> Step: """Append the last step. Call once, after the web output is written. Must be called BEFORE the notebook is built, because the notebook quotes the book measure and the measure is not complete until this step exists. - The site is this step's *artifact*. The notebook is not: it is the whole + The minisite is this step's *artifact*. The notebook is not: it is the whole sequence's rendering rather than an item in it, and it is set on `self.notebook` afterwards, by name only — a notebook cannot report its own byte count without changing it. @@ -273,10 +273,10 @@ class Book: summary = " · ".join(f"{v} {k}" for k, v in sorted(m["by_kind"].items(), key=lambda kv: -kv[1])) artifact, size = None, 0 - if site is not None: - site = Path(site) - if site.exists(): - artifact, size = str(site.relative_to(self.out)), _tree_bytes(site) + if minisite is not None: + minisite = Path(minisite) + if minisite.exists(): + artifact, size = str(minisite.relative_to(self.out)), _tree_bytes(minisite) self.steps.append(Step( id=LAST, label="what came out", diff --git a/soleprint/atlas2/docgen/book/build.py b/soleprint/atlas2/docgen/book/build.py index 0122b96..96a92e7 100644 --- a/soleprint/atlas2/docgen/book/build.py +++ b/soleprint/atlas2/docgen/book/build.py @@ -4,7 +4,7 @@ Run a book: larder, the steps, the web output, the book measure. python3 -m docgen book --root ../station -o out/book/station Composes functions that already exist. Nothing here parses, lays out or styles -anything — `ops.overview`, `emitters.auto.draw`, `emitters.site` and `notebook.spec` +anything — `ops.overview`, `emitters.auto.draw`, `emitters.minisite` and `notebook.spec` do all of it, and this decides the order and writes the ledger. If this file ever starts doing the work, the seam has moved to the wrong place. @@ -170,7 +170,7 @@ def spec_from(book: Book, ir: dict, *, prelude_dir: str | None = None) -> dict: f"**{summary} · {m['edges']} edges · {m['external']} external**\n\n" f"{len(m['artifacts'])} artifact(s), {m['bytes']:,} bytes.\n\n" f"Reconciled against what came in:\n\n{reconciled}\n\n" - "The web output is `site/index.html`." + "The web output is `minisite/index.html`." ), )) @@ -229,7 +229,9 @@ def _load_cell(step_id: str, artifact: str) -> str: # remove first. Named, never globbed: a book directory also holds the hand-written # `checks.py` and `overlay.json`, and a misconfigured output path could point at # somebody's source tree — so nothing outside this list is ever deleted. -GENERATED = ("book.json", "notebook.ipynb", "steps", "site", "explore", "document.json") +# `site` is the minisite's old name: a book built before the rename still has one. +GENERATED = ("book.json", "notebook.ipynb", "steps", "minisite", "site", "explore", + "document.json") # The steps a book runs, by id — fixed, so a note can be filed under one before # the book has ever been built, and a skipped step does not make its note drift. @@ -249,7 +251,7 @@ def clear(out) -> list[str]: """Remove a previous build's outputs from `out`. Returns what was removed. Without this, re-running a book leaves the last run's artifacts beside the new - ledger: a graph that is now `graph.md` keeps its old `graph.svg`, and the site + ledger: a graph that is now `graph.md` keeps its old `graph.svg`, and the minisite goes on showing it. The ledger would not list the stale file, so nothing would say it was stale — which is the failure the book measure exists to prevent. @@ -275,7 +277,7 @@ def clear(out) -> list[str]: def build_book(kind: str, source, out, *, slug: str | None = None, exclude=(), ops: dict | None = None, suffixes=None, quiet: bool = False) -> Book: - """One book's steps: larder, IR, view, pages, drawings. No site, no notebook. + """One book's steps: larder, IR, view, pages, drawings. No minisite, no notebook. Those are a document's outputs and are assembled by `book/document.py`, which may put several books into one of each. The book is returned open — its last @@ -385,8 +387,8 @@ def run(kind: str, source, out, *, slug: str | None = None, style: str = "lucid" quiet: bool = False) -> Book: """One book, as a one-book document whose outputs live in its own directory. - `book.json`, `steps/`, `site/` and `notebook.ipynb` land where they always did; - the site and notebook are now assembled the same way a many-book document's are. + `book.json`, `steps/`, `minisite/` and `notebook.ipynb` land where they always did; + the minisite and notebook are now assembled the same way a many-book document's are. """ from .document import Document, Output, Part, build @@ -397,7 +399,7 @@ def run(kind: str, source, out, *, slug: str | None = None, style: str = "lucid" notes=Path(notes) if notes else None, parts=[Part(name=slug, kind=kind, source=Path(source), out=out, exclude=tuple(exclude), overlay=overlay)], - outputs=[Output("site", out / "site", style=style, theme=theme), + outputs=[Output("minisite", out / "minisite", style=style, theme=theme), Output("notebook", out / "notebook.ipynb", style=style, theme=theme)], ) build(doc, quiet=quiet) @@ -412,6 +414,6 @@ def run(kind: str, source, out, *, slug: str | None = None, style: str = "lucid" f"{m['external']} external · {len(m['artifacts'])} artifacts") for r in book.compare(): print(f" {'ok ' if r['ok'] else 'LOST'} {r['claim']}") - print(f" open {out / 'site' / 'index.html'}") + print(f" open {out / 'minisite' / 'index.html'}") print(f" {out / 'book.json'}") return book diff --git a/soleprint/atlas2/docgen/book/checks.py b/soleprint/atlas2/docgen/book/checks.py index 3c56c5c..118892c 100644 --- a/soleprint/atlas2/docgen/book/checks.py +++ b/soleprint/atlas2/docgen/book/checks.py @@ -191,12 +191,12 @@ def generated(book: Loaded, r: Report) -> None: r.check(f"its {ran} code cells run, not merely compile", None, failure) r.note("the web output exists and shows both ends") - index = book.dir / "site" / "index.html" + index = book.dir / "minisite" / "index.html" if not index.exists(): - r.skip("site", "no site/index.html in this book") + r.skip("minisite", "no minisite/index.html in this book") else: html = index.read_text() - # The site is the last step precisely because it is the artifact somebody + # The minisite is the last step precisely because it is the artifact somebody # definitely opens. A page that shows the result without showing what # went in is the thing this whole change corrects. r.check("the page says what came in", True, "what came in" in html) @@ -205,7 +205,7 @@ def generated(book: Loaded, r: Report) -> None: r.check("the page admits the book is incomplete", True, "This book is incomplete" in html) - # A book built inline — its own site and notebook in its own directory — + # A book built inline — its own minisite and notebook in its own directory — # also carries the document ledger, and with it the notes it used. doc_ledger = book.dir / "document.json" if doc_ledger.is_file(): @@ -334,8 +334,8 @@ def document(build_dir, r: Report) -> None: r.skip("figures carry their SVG", f"{len(figures) - drawn} not drawn — Graphviz absent?") else: r.check("every figure carries its SVG, so it renders without running", True, True) - elif out["emitter"] == "site": - r.note(f"the site — {path}") + elif out["emitter"] == "minisite": + r.note(f"the minisite — {path}") index = path / "index.html" r.check("index.html exists", True, index.is_file()) if not index.is_file(): diff --git a/soleprint/atlas2/docgen/book/config.py b/soleprint/atlas2/docgen/book/config.py index bff8674..f7bb708 100644 --- a/soleprint/atlas2/docgen/book/config.py +++ b/soleprint/atlas2/docgen/book/config.py @@ -365,7 +365,7 @@ def run(runfile, names=None, *, check: bool = False, quiet: bool = True): # [project] name, title, notes, build, reference # [extract.] one book per table; [[extract.]] for several # [ops] applied to every book's view, before paging -# [emit.] notebook, site — each assembles every book +# [emit.] notebook, minisite — each assembles every book # # It compiles to the same Document a [[book]] entry does, so everything after # loading is one code path. @@ -382,7 +382,10 @@ EXTRACT_KEYS = { EXTRACT_SOURCE = {"python": "root", "code": "root", "db": "schema", "openapi": "spec", "usage": "har"} OPS_KEYS = {"drop_stdlib", "drop_builtins", "drop_external", "only", "drop"} -EMITTERS = {"notebook", "site"} +EMITTERS = {"notebook", "minisite"} +# Outputs that were renamed, with their new name. Refused with the rename rather +# than accepted quietly, so a run file says what it does. +RENAMED_EMITTERS = {"site": "minisite"} EMIT_KEYS = {"output", "style", "theme", "width"} # Keys a model reaches for that docgen deliberately does not do, with what to do @@ -526,9 +529,12 @@ def load_project(path: Path, data: dict) -> ProjectFile: emit = data.get("emit") or {} outputs = [] if not emit: - problems.append("no outputs — add [emit.notebook] or [emit.site] with an `output`") + problems.append("no outputs — add [emit.notebook] or [emit.minisite] with an `output`") for emitter, raw in emit.items(): where = f"[emit.{emitter}]" + if emitter in RENAMED_EMITTERS: + problems.append(f"{where} is now [emit.{RENAMED_EMITTERS[emitter]}] — rename the table") + continue if emitter not in EMITTERS: problems.append(f"{where}: no output named {emitter!r} — have: " f"{', '.join(sorted(EMITTERS))}") diff --git a/soleprint/atlas2/docgen/book/document.py b/soleprint/atlas2/docgen/book/document.py index 4de04b5..dc2a18c 100644 --- a/soleprint/atlas2/docgen/book/document.py +++ b/soleprint/atlas2/docgen/book/document.py @@ -4,18 +4,18 @@ A document: several books, assembled into each output. Document ├── books one per source — each keeps its own larder → steps → book ├── notes hand-written markdown, filed by page (book/notes.py) - └── outputs a notebook, a site, … — each one made of every book, as parts + └── outputs a notebook, a minisite, … — each one made of every book, as parts A book is a templated part of the final output, not the output itself. A project with an OpenAPI contract and a C# tree is one document of two books: one notebook -and one site, each with a part per book. A `[[book]]` run file is the same thing +and one minisite, each with a part per book. A `[[book]]` run file is the same thing with one book per document, which is what it always was. ## Built once, rendered per output Extraction, the view and the page structure happen once per book. Rendering -does not, because what a page looks like depends on where it is going: a site -column is narrower than a notebook cell, a site's boxes are links and a +does not, because what a page looks like depends on where it is going: a minisite +column is narrower than a notebook cell, a minisite's boxes are links and a notebook's cannot be, and each output can have its own theme. So each output lays the pages out for its own width and draws them itself. @@ -41,7 +41,7 @@ MANIFEST = ".docgen-output.json" @dataclass class Output: - emitter: str # "notebook" | "site" + emitter: str # "notebook" | "minisite" path: Path style: str = "lucid" theme: str | None = None @@ -329,20 +329,20 @@ def build(doc: Document, *, quiet: bool = True) -> Document: built_parts.append(part) doc.parts_built = built_parts - # Sites first: in a single inline book the site is its last step's artifact, - # and the notebook quotes the book measure — which only counts the site once - # the last step exists. - sites = [o for o in doc.outputs if o.emitter == "site"] + # Minisites first: in a single inline book the minisite is its last step's + # artifact, and the notebook quotes the book measure — which only counts the + # minisite once the last step exists. + sites = [o for o in doc.outputs if o.emitter == "minisite"] notebooks = [o for o in doc.outputs if o.emitter == "notebook"] written_outputs = [] for output in sites: - from ..emitters import docsite + from ..emitters import minisite site_dir = Path(output.path) clear_output(site_dir) style = Style.load(output.style, theme=output.theme) - width = output.width or docsite.CONTENT_WIDTH + width = output.width or minisite.CONTENT_WIDTH books = [] for book in doc.books: pages = rendered_pages(book, style, width, url=lambda p: f"{p['slug']}.html") @@ -358,16 +358,16 @@ def build(doc: Document, *, quiet: bool = True) -> Document: "intro": (intro, {}) if intro else None}) doc_intro = notes.document("_intro") doc_end = notes.document("_end") - files = docsite.write(site_dir, style, title=doc.title, books=books, - intro=doc_intro, end=doc_end, failed=doc.failed) + files = minisite.write(site_dir, style, title=doc.title, books=books, + intro=doc_intro, end=doc_end, failed=doc.failed) write_manifest(site_dir, files) - written_outputs.append({"emitter": "site", "path": str(site_dir), "width": width, + written_outputs.append({"emitter": "minisite", "path": str(site_dir), "width": width, "files": len(files)}) - say(f" site {site_dir / 'index.html'}") + say(f" minisite {site_dir / 'index.html'}") for book in doc.books: inside = [o for o in sites if doc.inline and Path(o.path).parent == book.out] - book.close(site=Path(inside[0].path) if inside else None) + book.close(minisite=Path(inside[0].path) if inside else None) for output in notebooks: path = Path(output.path) diff --git a/soleprint/atlas2/docgen/cli/emit.py b/soleprint/atlas2/docgen/cli/emit.py index 54d283f..55582b8 100644 --- a/soleprint/atlas2/docgen/cli/emit.py +++ b/soleprint/atlas2/docgen/cli/emit.py @@ -5,7 +5,7 @@ python3 -m docgen emit index [-o out.md|.json] python3 -m docgen emit minimap [-o out.svg] [--scale 0.55] python3 -m docgen emit notebook [-o out.ipynb] [--overlay f.json] - python3 -m docgen emit site -o DIR + python3 -m docgen emit minisite -o DIR python3 -m docgen emit explore -o DIR IR -> an artifact. Every emitter validates its input first, so a broken document @@ -182,8 +182,8 @@ def notebook(argv) -> int: return 0 -def site(argv) -> int: - p = argparse.ArgumentParser(prog=f"{PROG} emit site") +def minisite(argv) -> int: + p = argparse.ArgumentParser(prog=f"{PROG} emit minisite") p.add_argument("ir", type=Path) p.add_argument("--output", "-o", type=Path, required=True, help="Directory.") style_args(p) @@ -191,7 +191,7 @@ def site(argv) -> int: p.add_argument("--no-graph", action="store_true") args = p.parse_args(argv) from ..emitters.auto import draw - from ..emitters.site import write as site_write + from ..emitters.minisite.onepage import write as page_write data, style = read_ir(args.ir), load_style(args.style, args.theme) args.output.mkdir(parents=True, exist_ok=True) @@ -208,10 +208,10 @@ def site(argv) -> int: print(f" note: {drawn['verdict']['kind']} — {drawn['why']}", file=sys.stderr) print(" no diagram on the page; the index is the artifact", file=sys.stderr) - for f in site_write(data, style, args.output, graph=graph_name, title=args.title): - print(f" site {f}") + for f in page_write(data, style, args.output, graph=graph_name, title=args.title): + print(f" minisite {f}") if graph_name: - print(f" site {args.output / graph_name}") + print(f" minisite {args.output / graph_name}") return 0 @@ -240,13 +240,17 @@ def explore(argv) -> int: EMITTERS = {"auto": auto, "dot": dot, "erd": erd, "index": index, "minimap": minimap, - "notebook": notebook, "site": site, "explore": explore} + "notebook": notebook, "minisite": minisite, "explore": explore} +# Renamed emitters, so the old name says what to type instead. +RENAMED = {"site": "minisite"} def main(argv) -> int: if not argv or argv[0] in ("-h", "--help"): print(__doc__.strip("\n")) return 0 if argv else 2 + if argv[0] in RENAMED: + raise Abort(f"emit {argv[0]} is now emit {RENAMED[argv[0]]}") if argv[0] not in EMITTERS: raise Abort(f"no emitter {argv[0]!r} — have: {', '.join(EMITTERS)}") return EMITTERS[argv[0]](argv[1:]) diff --git a/soleprint/atlas2/docgen/docgen.project.example.toml b/soleprint/atlas2/docgen/docgen.project.example.toml index fa574f9..1e78e59 100644 --- a/soleprint/atlas2/docgen/docgen.project.example.toml +++ b/soleprint/atlas2/docgen/docgen.project.example.toml @@ -48,6 +48,6 @@ output = "out/project/notebook" # a directory: .ipynb goes inside theme = "lucid" width = 960 # px — pages are split until each fits -[emit.site] -output = "out/project/site" +[emit.minisite] +output = "out/project/minisite" theme = "dark" diff --git a/soleprint/atlas2/docgen/docs/img/architecture.svg b/soleprint/atlas2/docgen/docs/img/architecture.svg index 001a373..6bbaceb 100644 --- a/soleprint/atlas2/docgen/docs/img/architecture.svg +++ b/soleprint/atlas2/docgen/docs/img/architecture.svg @@ -4,72 +4,77 @@ - - + + ir - + cluster_docgen - -docgen + +docgen cluster_docgen_book - -book + +book cluster_docgen_cli - -cli + +cli cluster_docgen_emitters - -emitters + +emitters + + +cluster_docgen_emitters_minisite + +minisite cluster_docgen_extractors - -extractors + +extractors cluster_docgen_extractors_python - -python + +python cluster_docgen_ir - -ir + +ir cluster_docgen_lab - -lab + +lab cluster_docgen_notebook - -notebook + +notebook cluster_docgen_ops - -ops + +ops cluster_docgen_style - -style + +style docgen.__main__ - -__main__ + +__main__ @@ -77,23 +82,23 @@ docgen.cli.book - -book + +book docgen.__main__->docgen.cli.book - - + + docgen.book.build - -build + +build @@ -101,82 +106,82 @@ docgen.book.document - -document + +document docgen.book.build->docgen.book.document - - + + docgen.book.larder - -larder + +larder docgen.book.build->docgen.book.larder - - + + docgen.book.build->docgen.book.larder - - + + docgen.emitters.auto - -auto + +auto docgen.book.build->docgen.emitters.auto - - + + docgen.emitters.explore - -explore + +explore docgen.book.build->docgen.emitters.explore - - + + docgen.emitters.index - -index + +index docgen.book.build->docgen.emitters.index - - + + @@ -190,891 +195,876 @@ docgen.book.build->docgen.emitters.minimap - - + + docgen.ir.model - -model + +model docgen.book.build->docgen.ir.model - - + + docgen.notebook.spec - -spec + +spec docgen.book.build->docgen.notebook.spec - - + + docgen.ops.filter - -filter + +filter docgen.book.build->docgen.ops.filter - - + + docgen.ops.pages - -pages + +pages docgen.book.build->docgen.ops.pages - - + + docgen.style.extract - -extract + +extract docgen.book.build->docgen.style.extract - - + + docgen.book.checks - -checks + +checks docgen.book.checks->docgen.book.build - - + + docgen.book.config - -config + +config docgen.book.config->docgen.__main__ - - + + docgen.book.config->docgen.book.build - - + + docgen.book.config->docgen.book.build - - + + docgen.book.config->docgen.book.document - - + + docgen.extractors.code - -code + +code docgen.book.config->docgen.extractors.code - - + + docgen.book.config->docgen.notebook.spec - - + + docgen.book.document->docgen.book.build - - + + docgen.book.document->docgen.book.build - - + + docgen.book.document->docgen.book.larder - - + + docgen.book.notes - -notes + +notes docgen.book.document->docgen.book.notes - - + + docgen.book.document->docgen.emitters.auto - - + + docgen.emitters.notebook - -notebook + +notebook docgen.book.document->docgen.emitters.notebook - - + + docgen.emitters.paged - -paged + +paged docgen.book.document->docgen.emitters.paged - - + + docgen.book.document->docgen.notebook.spec - - + + docgen.book.document->docgen.ops.filter - - + + docgen.book.document->docgen.ops.pages - - + + docgen.book.document->docgen.style.extract - - + + docgen.cli.book->docgen.book.build - - + + docgen.cli.common - -common + +common docgen.cli.book->docgen.cli.common - - + + docgen.cli.book->docgen.cli.common - - + + docgen.cli.book->docgen.notebook.spec - - + + docgen.cli.check - -check + +check docgen.cli.check->docgen.book.checks - - + + docgen.cli.check->docgen.cli.common - - + + docgen.cli.common->docgen.ir.model - - + + docgen.cli.common->docgen.style.extract - - + + docgen.cli.contract - -contract + +contract docgen.cli.contract->docgen.cli.common - - + + docgen.cli.emit - -emit + +emit docgen.cli.emit->docgen.cli.common - - + + docgen.cli.emit->docgen.emitters.auto - - + + docgen.emitters.dot - -dot + +dot docgen.cli.emit->docgen.emitters.dot - - + + docgen.emitters.erd - -erd + +erd docgen.cli.emit->docgen.emitters.erd - - + + docgen.cli.emit->docgen.emitters.explore - - + + docgen.cli.emit->docgen.emitters.index - - + + docgen.cli.emit->docgen.emitters.minimap - - - - - -docgen.cli.emit->docgen.emitters.notebook - - - - - -docgen.emitters.site - - -site + + + + + +docgen.emitters.minisite.onepage + + +onepage - + + +docgen.cli.emit->docgen.emitters.minisite.onepage + + + + -docgen.cli.emit->docgen.emitters.site - - +docgen.cli.emit->docgen.emitters.notebook + + docgen.cli.emit->docgen.notebook.spec - - + + docgen.cli.emit->docgen.ops.filter - - + + docgen.cli.extract - -extract + +extract docgen.cli.extract->docgen.cli.common - - + + docgen.cli.extract->docgen.extractors.code - - + + docgen.extractors.db - -db + +db docgen.cli.extract->docgen.extractors.db - - + + docgen.extractors.openapi - -openapi + +openapi docgen.cli.extract->docgen.extractors.openapi - - + + docgen.extractors.python.collect - -collect + +collect docgen.cli.extract->docgen.extractors.python.collect - - + + docgen.extractors.usage - -usage + +usage docgen.cli.extract->docgen.extractors.usage - - + + docgen.cli.run - -run + +run docgen.cli.run->docgen.book.config - - + + docgen.cli.run->docgen.cli.common - - + + docgen.cli.scaffold - -scaffold + +scaffold docgen.cli.scaffold->docgen.book.config - - + + docgen.cli.scaffold->docgen.book.document - - + + docgen.cli.scaffold->docgen.book.notes - - + + docgen.cli.scaffold->docgen.cli.common - - + + docgen.cli.validate - -validate + +validate docgen.cli.validate->docgen.cli.common - - + + docgen.ir.validate - -validate + +validate docgen.cli.validate->docgen.ir.validate - - + + docgen.cli.view - -view + +view docgen.cli.view->docgen.cli.common - - + + docgen.cli.view->docgen.ir.model - - + + docgen.cli.view->docgen.ops.filter - - + + docgen.emitters.auto->docgen.emitters.dot - - + + docgen.emitters.auto->docgen.emitters.erd - - + + docgen.emitters.auto->docgen.emitters.index - - + + docgen.emitters.auto->docgen.ops.filter - - - - - -docgen.emitters.docsite - - -docsite - - + + - + -docgen.emitters.docsite->docgen.book.document - - - - - -docgen.emitters.markdown - - -markdown - - +docgen.emitters.explore->docgen.emitters.dot + + - + -docgen.emitters.docsite->docgen.emitters.markdown - - +docgen.emitters.explore->docgen.emitters.erd + + - + -docgen.emitters.docsite->docgen.emitters.paged - - +docgen.emitters.explore->docgen.emitters.minimap + + - + -docgen.emitters.docsite->docgen.emitters.site - - +docgen.emitters.explore->docgen.ops.filter + + - + + +docgen.emitters.markdown + + +markdown + + + + -docgen.emitters.explore->docgen.emitters.dot - - +docgen.emitters.minisite.onepage->docgen.book.document + + - + + +docgen.emitters.minisite.onepage->docgen.emitters.index + + + + -docgen.emitters.explore->docgen.emitters.erd - - +docgen.emitters.minisite.onepage->docgen.emitters.markdown + + - + -docgen.emitters.explore->docgen.emitters.minimap - - - - - -docgen.emitters.explore->docgen.ops.filter - - +docgen.emitters.minisite.onepage->docgen.emitters.paged + + docgen.emitters.paged->docgen.emitters.dot - - + + docgen.emitters.paged->docgen.emitters.erd - - + + docgen.emitters.paged->docgen.ops.filter - - - - - -docgen.emitters.site->docgen.emitters.index - - + + - + docgen.extractors.code->docgen.book.larder - - + + - + docgen.extractors.code->docgen.ir.model - - + + tree_sitter - -tree_sitter + +tree_sitter - + docgen.extractors.code->tree_sitter - - + + - + docgen.extractors.db->docgen.book.larder - - + + - + docgen.extractors.db->docgen.ir.model - - + + - + docgen.extractors.openapi->docgen.__main__ - - + + - + docgen.extractors.openapi->docgen.book.larder - - + + - + docgen.extractors.openapi->docgen.ir.model - - + + modelgen.loader.extract.openapi - -openapi + +openapi - + docgen.extractors.openapi->modelgen.loader.extract.openapi - - + + yaml - -yaml + +yaml - + docgen.extractors.openapi->yaml - - + + docgen.extractors.python.resolve - -resolve + +resolve - + docgen.extractors.python.collect->docgen.extractors.python.resolve - - + + - + docgen.extractors.python.resolve->docgen.book.larder - - + + - + docgen.extractors.python.resolve->docgen.extractors.python.collect - - + + - + docgen.extractors.python.resolve->docgen.ir.model - - + + - + docgen.extractors.usage->docgen.book.larder - - + + - + docgen.extractors.usage->docgen.ir.model - - + + - + docgen.ir.model->docgen.ir.validate - - + + - + docgen.ir.validate->docgen.ir.model - - + + docgen.lab.pg_probe - -pg_probe + +pg_probe - + docgen.ops.pages->docgen.ops.filter - - + + docgen.reference - -reference + +reference @@ -1082,49 +1072,49 @@ docgen.selftest - -selftest + +selftest lxml - -lxml + +lxml - + docgen.selftest->lxml - - + + docgen.style.tokens - -tokens + +tokens - + docgen.style.extract->docgen.style.tokens - - + + - + docgen.style.extract->lxml - - + + - + docgen.style.tokens->docgen.style.extract - - + + diff --git a/soleprint/atlas2/docgen/docs/img/minimap.svg b/soleprint/atlas2/docgen/docs/img/minimap.svg index c132b2f..99f7c64 100644 --- a/soleprint/atlas2/docgen/docs/img/minimap.svg +++ b/soleprint/atlas2/docgen/docs/img/minimap.svg @@ -1,7 +1,7 @@ - - -docgen.selftest — 2775 lines + + +docgen.selftest — 2783 lines own_py_files — function, 3 lines check — function, 5 lines _err — function, 7 lines @@ -11,16 +11,16 @@ _entry — function, 7 lines _books — function, 279 lines _standalone — function, 153 lines -_layout — function, 89 lines -_runfiles — function, 195 lines -write — function, 4 lines -problems — function, 6 lines -_pages — function, 114 lines -_documents — function, 161 lines -_projects — function, 59 lines -load — function, 7 lines -_contract — function, 75 lines -named — function, 2 lines +_layout — function, 92 lines +_runfiles — function, 195 lines +write — function, 4 lines +problems — function, 6 lines +_pages — function, 114 lines +_documents — function, 161 lines +_projects — function, 64 lines +load — function, 7 lines +_contract — function, 75 lines +named — function, 2 lines docgen.book — 316 lines Step — class, 20 lines to_dict — function, 10 lines @@ -68,380 +68,383 @@ docgen.emitters — 12 lines docgen.lab — 11 lines docgen.__main__ — 9 lines -docgen.ir — 7 lines -docgen.extractors — 2 lines -docgen.emitters.site — 539 lines -_ledger — function, 54 lines -_slots — function, 15 lines -_fill — function, 4 lines -_sidebar — function, 17 lines -_sections — function, 15 lines -emit — function, 96 lines -write — function, 10 lines -docgen.emitters.notebook — 320 lines -_cell — function, 19 lines -_example — function, 26 lines -_params_cell — function, 18 lines -_call_cell — function, 40 lines -_call_md — function, 26 lines -_figure_md — function, 21 lines -_figure_attachments — function, 7 lines -build — function, 55 lines -emit — function, 3 lines -write — function, 5 lines -docgen.emitters.explore — 316 lines -_is_schema — function, 4 lines -_neighbourhood_svgs — function, 48 lines -render_one — function, 2 lines -render_one — function, 2 lines -_facts — function, 27 lines -emit — function, 172 lines -write — function, 17 lines -docgen.emitters.dot — 309 lines -RenderError — class, 2 lines -_esc — function, 2 lines -_attrs — function, 3 lines -_style_words — function, 9 lines -_node_attrs — function, 33 lines -emit — function, 113 lines -write — function, 31 lines -_within — function, 8 lines -_endpoints — function, 41 lines -walk — function, 4 lines -collapsed — function, 2 lines -first_leaf — function, 4 lines -_safe — function, 2 lines -_q — function, 2 lines -have_graphviz — function, 2 lines -render — function, 29 lines -docgen.emitters.minimap — 278 lines -_files — function, 57 lines -declared — function, 18 lines -build — function, 11 lines -_bands — function, 7 lines -_blocks — function, 19 lines -emit — function, 120 lines -marks_to_labels — function, 3 lines -docgen.emitters.erd — 276 lines -_truncate — function, 3 lines -_tables — function, 20 lines -_card_height — function, 3 lines -max_columns — function, 9 lines -layout — function, 25 lines -_field_y — function, 3 lines -emit — function, 146 lines -docgen.emitters.docsite — 270 lines -_note — function, 7 lines -_missing — function, 9 lines -_tree — function, 15 lines -walk — function, 7 lines -_page — function, 69 lines -write — function, 95 lines -put — function, 4 lines -docgen.emitters.index — 164 lines -_tree — function, 8 lines -_anchor — function, 5 lines -to_markdown — function, 84 lines -walk — function, 27 lines -to_sidebar — function, 26 lines -build — function, 13 lines -docgen.emitters.markdown — 146 lines -_url — function, 7 lines -_inline — function, 13 lines -keep — function, 3 lines -to_html — function, 91 lines -para — function, 3 lines -cells — function, 2 lines -docgen.emitters.paged — 119 lines -svg_width_px — function, 6 lines -_estimate_px — function, 10 lines -fits_for — function, 17 lines -fits — function, 6 lines -links_for — function, 15 lines -render — function, 19 lines -inline — function, 9 lines -docgen.emitters.auto — 64 lines -draw — function, 36 lines -docgen.cli.emit — 253 lines -_parser — function, 7 lines -_size — function, 3 lines -auto — function, 16 lines -dot — function, 38 lines -erd — function, 11 lines -index — function, 14 lines -minimap — function, 14 lines -notebook — function, 41 lines -site — function, 31 lines -explore — function, 22 lines -main — function, 7 lines -docgen.cli.extract — 119 lines -_parser — function, 5 lines -_counts — function, 3 lines -python — function, 15 lines -code — function, 14 lines -db — function, 11 lines -openapi — function, 12 lines -usage — function, 15 lines -main — function, 7 lines -docgen.cli.run — 99 lines -main — function, 78 lines -docgen.cli.view — 90 lines -main — function, 75 lines -docgen.cli.scaffold — 88 lines -main — function, 66 lines -docgen.cli.common — 80 lines -Abort — class, 2 lines -read_json — function, 5 lines -read_ir — function, 11 lines -load_style — function, 7 lines -style_args — function, 3 lines -emit — function, 16 lines -dump_ir — function, 3 lines -docgen.cli.book — 77 lines -main — function, 55 lines -docgen.cli.check — 58 lines -main — function, 37 lines -docgen.cli.contract — 34 lines -main — function, 8 lines -docgen.cli.validate — 33 lines -main — function, 18 lines -docgen.book.config — 616 lines -ConfigError — class, 6 lines -__init__ — function, 3 lines -Entry — class, 15 lines -line — function, 2 lines -RunFile — class, 17 lines -select — function, 12 lines -_path — function, 6 lines -_within — function, 3 lines -_read — function, 9 lines -load — function, 18 lines -_load_books — function, 121 lines -pick — function, 3 lines -apply_reference — function, 11 lines -_checks — function, 13 lines -run — function, 36 lines -ProjectFile — class, 8 lines -books — function, 2 lines -load_project — function, 151 lines -select_parts — function, 9 lines -run_project — function, 41 lines -docgen.book.document — 449 lines -Output — class, 6 lines -Part — class, 11 lines -Document — class, 11 lines -apply_ops — function, 15 lines -clear_output — function, 27 lines -write_manifest — function, 3 lines -rendered_pages — function, 22 lines -caption — function, 14 lines -_note_step — function, 8 lines -_with_note — function, 11 lines -notebook_spec — function, 91 lines -build — function, 116 lines -say — function, 3 lines -_spots — function, 16 lines -known_spots — function, 3 lines -plan_spots — function, 9 lines -docgen.book.build — 418 lines -extract — function, 29 lines -spec_from — function, 71 lines -_load_cell — function, 46 lines -clear — function, 26 lines -build_book — function, 105 lines -say — function, 3 lines -run — function, 35 lines -docgen.book.checks — 378 lines -Loaded — class, 26 lines -__init__ — function, 15 lines -larder — function, 2 lines -measure — function, 2 lines -Report — class, 38 lines -__init__ — function, 3 lines -note — function, 2 lines -check — function, 8 lines -skip — function, 3 lines -total — function, 15 lines -generated — function, 89 lines -custom — function, 26 lines -_run_cells — function, 33 lines -_notes_drift — function, 7 lines -document — function, 72 lines -heading — function, 2 lines -document_failures — function, 9 lines -docgen.book.larder — 196 lines -_count — function, 13 lines -redact — function, 32 lines -Larder — class, 77 lines -__post_init__ — function, 7 lines -read — function, 3 lines -fail — function, 3 lines -to_dict — function, 13 lines -from_dict — function, 10 lines -line — function, 20 lines -of — function, 3 lines -docgen.book.notes — 162 lines -body — function, 6 lines -stub — function, 3 lines -Notes — class, 78 lines -__init__ — function, 3 lines -_read — function, 7 lines -document — function, 2 lines -book — function, 2 lines -path — function, 4 lines -drift — function, 27 lines -scaffold — function, 24 lines -images — function, 18 lines -data_uri — function, 2 lines -docgen.extractors.code — 282 lines -MissingParser — class, 2 lines -_parser — function, 21 lines -_name — function, 10 lines -_walk — function, 34 lines -extract_file — function, 27 lines -_count_errors — function, 5 lines -extract — function, 75 lines -docgen.extractors.usage — 269 lines -_template — function, 27 lines -_body — function, 10 lines -_shape — function, 15 lines -_graphql — function, 11 lines -extract — function, 133 lines -docgen.extractors.openapi — 191 lines -_modelgen — function, 28 lines -_type_name — function, 6 lines -_refs — function, 43 lines -extract — function, 76 lines -docgen.extractors.db — 161 lines -from_schema_dict — function, 82 lines -_relation — function, 10 lines -_plain_type — function, 6 lines -_dedupe — function, 9 lines -extract — function, 6 lines -docgen.extractors.python — 37 lines -extract — function, 14 lines -docgen.extractors.python.collect — 236 lines -Definition — class, 10 lines -Module — class, 12 lines -_Collector — class, 67 lines -__init__ — function, 3 lines -_define — function, 17 lines -visit_ClassDef — function, 5 lines -visit_FunctionDef — function, 5 lines -visit_Import — function, 8 lines -visit_ImportFrom — function, 14 lines -_first_line — function, 5 lines -_name_of — function, 15 lines -_resolve_relative — function, 16 lines -module_name — function, 26 lines -collect_file — function, 21 lines -collect — function, 13 lines -docgen.extractors.python.resolve — 184 lines -_id_for — function, 2 lines -_resolve — function, 32 lines -larder_of — function, 17 lines -to_ir — function, 98 lines -_point_at — function, 9 lines -docgen.ir.validate — 278 lines -IRError — class, 2 lines -_schema — function, 2 lines -_props — function, 5 lines -_fields — function, 4 lines -check — function, 108 lines -_check_larder — function, 58 lines -validate — function, 6 lines -check_model_matches_schema — function, 23 lines -docgen.ir.model — 165 lines -Meta — class, 38 lines -to_dict — function, 18 lines -Node — class, 21 lines -__post_init__ — function, 3 lines -to_dict — function, 8 lines -Edge — class, 15 lines -to_dict — function, 7 lines -Graph — class, 48 lines -node — function, 4 lines -edge — function, 4 lines -has — function, 2 lines -to_dict — function, 16 lines -from_dict — function, 6 lines -docgen.ops.filter — 485 lines -_rebuild — function, 57 lines -surviving_parent — function, 5 lines -lift — function, 6 lines -drop_kinds — function, 14 lines -only_kinds — function, 14 lines -drop_stdlib — function, 13 lines -drop_external — function, 3 lines -subtree — function, 13 lines -neighbourhood — function, 45 lines -collapse_to_depth — function, 18 lines -level — function, 6 lines -drop_builtins — function, 14 lines -overview — function, 35 lines -shape — function, 72 lines -rank_of — function, 9 lines -split — function, 24 lines -classify — function, 102 lines -docgen.ops.pages — 383 lines -slugify — function, 8 lines -_key — function, 8 lines -_under — function, 5 lines -_representative — function, 13 lines -page_ir — function, 67 lines -layout — function, 20 lines -paginate — function, 61 lines -unique — function, 6 lines -opens — function, 3 lines -visit — function, 30 lines -paginate_tables — function, 76 lines -coverage — function, 28 lines -for_view — function, 17 lines -docgen.style.extract — 222 lines -_values_from — function, 17 lines -_normalise — function, 45 lines -_svg_files — function, 25 lines -harvest — function, 43 lines -write — function, 7 lines -summarise — function, 13 lines -docgen.style.tokens — 211 lines -_top — function, 2 lines -_mode — function, 3 lines -_luminance — function, 6 lines -derive — function, 101 lines -accent — function, 2 lines -geometry — function, 14 lines -write — function, 7 lines -from_folder — function, 9 lines -docgen — 2 lines -docgen.lab.pg_probe — 150 lines -probe — function, 30 lines -_simplify — function, 3 lines -main — function, 25 lines -docgen.notebook.spec — 264 lines -_step — function, 4 lines -from_ir — function, 108 lines -_order — function, 5 lines -scaffold — function, 20 lines -merge — function, 58 lines -load — function, 2 lines -dump — function, 5 lines +docgen.ir — 7 lines +docgen.extractors — 2 lines +docgen.cli.emit — 257 lines +_parser — function, 7 lines +_size — function, 3 lines +auto — function, 16 lines +dot — function, 38 lines +erd — function, 11 lines +index — function, 14 lines +minimap — function, 14 lines +notebook — function, 41 lines +minisite — function, 31 lines +explore — function, 22 lines +main — function, 9 lines +docgen.cli.extract — 119 lines +_parser — function, 5 lines +_counts — function, 3 lines +python — function, 15 lines +code — function, 14 lines +db — function, 11 lines +openapi — function, 12 lines +usage — function, 15 lines +main — function, 7 lines +docgen.cli.run — 99 lines +main — function, 78 lines +docgen.cli.view — 90 lines +main — function, 75 lines +docgen.cli.scaffold — 88 lines +main — function, 66 lines +docgen.cli.common — 80 lines +Abort — class, 2 lines +read_json — function, 5 lines +read_ir — function, 11 lines +load_style — function, 7 lines +style_args — function, 3 lines +emit — function, 16 lines +dump_ir — function, 3 lines +docgen.cli.book — 77 lines +main — function, 55 lines +docgen.cli.check — 58 lines +main — function, 37 lines +docgen.cli.contract — 34 lines +main — function, 8 lines +docgen.cli.validate — 33 lines +main — function, 18 lines +docgen.emitters.notebook — 320 lines +_cell — function, 19 lines +_example — function, 26 lines +_params_cell — function, 18 lines +_call_cell — function, 40 lines +_call_md — function, 26 lines +_figure_md — function, 21 lines +_figure_attachments — function, 7 lines +build — function, 55 lines +emit — function, 3 lines +write — function, 5 lines +docgen.emitters.explore — 316 lines +_is_schema — function, 4 lines +_neighbourhood_svgs — function, 48 lines +render_one — function, 2 lines +render_one — function, 2 lines +_facts — function, 27 lines +emit — function, 172 lines +write — function, 17 lines +docgen.emitters.dot — 309 lines +RenderError — class, 2 lines +_esc — function, 2 lines +_attrs — function, 3 lines +_style_words — function, 9 lines +_node_attrs — function, 33 lines +emit — function, 113 lines +write — function, 31 lines +_within — function, 8 lines +_endpoints — function, 41 lines +walk — function, 4 lines +collapsed — function, 2 lines +first_leaf — function, 4 lines +_safe — function, 2 lines +_q — function, 2 lines +have_graphviz — function, 2 lines +render — function, 29 lines +docgen.emitters.minimap — 278 lines +_files — function, 57 lines +declared — function, 18 lines +build — function, 11 lines +_bands — function, 7 lines +_blocks — function, 19 lines +emit — function, 120 lines +marks_to_labels — function, 3 lines +docgen.emitters.erd — 276 lines +_truncate — function, 3 lines +_tables — function, 20 lines +_card_height — function, 3 lines +max_columns — function, 9 lines +layout — function, 25 lines +_field_y — function, 3 lines +emit — function, 146 lines +docgen.emitters.minisite — 270 lines +_note — function, 7 lines +_missing — function, 9 lines +_tree — function, 15 lines +walk — function, 7 lines +_page — function, 69 lines +write — function, 95 lines +put — function, 4 lines +docgen.emitters.index — 164 lines +_tree — function, 8 lines +_anchor — function, 5 lines +to_markdown — function, 84 lines +walk — function, 27 lines +to_sidebar — function, 26 lines +build — function, 13 lines +docgen.emitters.markdown — 146 lines +_url — function, 7 lines +_inline — function, 13 lines +keep — function, 3 lines +to_html — function, 91 lines +para — function, 3 lines +cells — function, 2 lines +docgen.emitters.paged — 119 lines +svg_width_px — function, 6 lines +_estimate_px — function, 10 lines +fits_for — function, 17 lines +fits — function, 6 lines +links_for — function, 15 lines +render — function, 19 lines +inline — function, 9 lines +docgen.emitters.auto — 64 lines +draw — function, 36 lines +docgen.book.config — 622 lines +ConfigError — class, 6 lines +__init__ — function, 3 lines +Entry — class, 15 lines +line — function, 2 lines +RunFile — class, 17 lines +select — function, 12 lines +_path — function, 6 lines +_within — function, 3 lines +_read — function, 9 lines +load — function, 18 lines +_load_books — function, 121 lines +pick — function, 3 lines +apply_reference — function, 11 lines +_checks — function, 13 lines +run — function, 36 lines +ProjectFile — class, 8 lines +books — function, 2 lines +load_project — function, 154 lines +select_parts — function, 9 lines +run_project — function, 41 lines +docgen.book.document — 449 lines +Output — class, 6 lines +Part — class, 11 lines +Document — class, 11 lines +apply_ops — function, 15 lines +clear_output — function, 27 lines +write_manifest — function, 3 lines +rendered_pages — function, 22 lines +caption — function, 14 lines +_note_step — function, 8 lines +_with_note — function, 11 lines +notebook_spec — function, 91 lines +build — function, 116 lines +say — function, 3 lines +_spots — function, 16 lines +known_spots — function, 3 lines +plan_spots — function, 9 lines +docgen.book.build — 420 lines +extract — function, 29 lines +spec_from — function, 71 lines +_load_cell — function, 46 lines +clear — function, 26 lines +build_book — function, 105 lines +say — function, 3 lines +run — function, 35 lines +docgen.book.checks — 378 lines +Loaded — class, 26 lines +__init__ — function, 15 lines +larder — function, 2 lines +measure — function, 2 lines +Report — class, 38 lines +__init__ — function, 3 lines +note — function, 2 lines +check — function, 8 lines +skip — function, 3 lines +total — function, 15 lines +generated — function, 89 lines +custom — function, 26 lines +_run_cells — function, 33 lines +_notes_drift — function, 7 lines +document — function, 72 lines +heading — function, 2 lines +document_failures — function, 9 lines +docgen.book.larder — 196 lines +_count — function, 13 lines +redact — function, 32 lines +Larder — class, 77 lines +__post_init__ — function, 7 lines +read — function, 3 lines +fail — function, 3 lines +to_dict — function, 13 lines +from_dict — function, 10 lines +line — function, 20 lines +of — function, 3 lines +docgen.book.notes — 162 lines +body — function, 6 lines +stub — function, 3 lines +Notes — class, 78 lines +__init__ — function, 3 lines +_read — function, 7 lines +document — function, 2 lines +book — function, 2 lines +path — function, 4 lines +drift — function, 27 lines +scaffold — function, 24 lines +images — function, 18 lines +data_uri — function, 2 lines +docgen.extractors.code — 282 lines +MissingParser — class, 2 lines +_parser — function, 21 lines +_name — function, 10 lines +_walk — function, 34 lines +extract_file — function, 27 lines +_count_errors — function, 5 lines +extract — function, 75 lines +docgen.extractors.usage — 269 lines +_template — function, 27 lines +_body — function, 10 lines +_shape — function, 15 lines +_graphql — function, 11 lines +extract — function, 133 lines +docgen.extractors.openapi — 191 lines +_modelgen — function, 28 lines +_type_name — function, 6 lines +_refs — function, 43 lines +extract — function, 76 lines +docgen.extractors.db — 161 lines +from_schema_dict — function, 82 lines +_relation — function, 10 lines +_plain_type — function, 6 lines +_dedupe — function, 9 lines +extract — function, 6 lines +docgen.extractors.python — 37 lines +extract — function, 14 lines +docgen.extractors.python.collect — 236 lines +Definition — class, 10 lines +Module — class, 12 lines +_Collector — class, 67 lines +__init__ — function, 3 lines +_define — function, 17 lines +visit_ClassDef — function, 5 lines +visit_FunctionDef — function, 5 lines +visit_Import — function, 8 lines +visit_ImportFrom — function, 14 lines +_first_line — function, 5 lines +_name_of — function, 15 lines +_resolve_relative — function, 16 lines +module_name — function, 26 lines +collect_file — function, 21 lines +collect — function, 13 lines +docgen.extractors.python.resolve — 184 lines +_id_for — function, 2 lines +_resolve — function, 32 lines +larder_of — function, 17 lines +to_ir — function, 98 lines +_point_at — function, 9 lines +docgen.ir.validate — 278 lines +IRError — class, 2 lines +_schema — function, 2 lines +_props — function, 5 lines +_fields — function, 4 lines +check — function, 108 lines +_check_larder — function, 58 lines +validate — function, 6 lines +check_model_matches_schema — function, 23 lines +docgen.ir.model — 165 lines +Meta — class, 38 lines +to_dict — function, 18 lines +Node — class, 21 lines +__post_init__ — function, 3 lines +to_dict — function, 8 lines +Edge — class, 15 lines +to_dict — function, 7 lines +Graph — class, 48 lines +node — function, 4 lines +edge — function, 4 lines +has — function, 2 lines +to_dict — function, 16 lines +from_dict — function, 6 lines +docgen.ops.filter — 485 lines +_rebuild — function, 57 lines +surviving_parent — function, 5 lines +lift — function, 6 lines +drop_kinds — function, 14 lines +only_kinds — function, 14 lines +drop_stdlib — function, 13 lines +drop_external — function, 3 lines +subtree — function, 13 lines +neighbourhood — function, 45 lines +collapse_to_depth — function, 18 lines +level — function, 6 lines +drop_builtins — function, 14 lines +overview — function, 35 lines +shape — function, 72 lines +rank_of — function, 9 lines +split — function, 24 lines +classify — function, 102 lines +docgen.ops.pages — 383 lines +slugify — function, 8 lines +_key — function, 8 lines +_under — function, 5 lines +_representative — function, 13 lines +page_ir — function, 67 lines +layout — function, 20 lines +paginate — function, 61 lines +unique — function, 6 lines +opens — function, 3 lines +visit — function, 30 lines +paginate_tables — function, 76 lines +coverage — function, 28 lines +for_view — function, 17 lines +docgen.style.extract — 222 lines +_values_from — function, 17 lines +_normalise — function, 45 lines +_svg_files — function, 25 lines +harvest — function, 43 lines +write — function, 7 lines +summarise — function, 13 lines +docgen.style.tokens — 211 lines +_top — function, 2 lines +_mode — function, 3 lines +_luminance — function, 6 lines +derive — function, 101 lines +accent — function, 2 lines +geometry — function, 14 lines +write — function, 7 lines +from_folder — function, 9 lines +docgen — 2 lines +docgen.emitters.minisite.onepage — 541 lines +_ledger — function, 54 lines +_slots — function, 15 lines +_fill — function, 4 lines +_sidebar — function, 17 lines +_sections — function, 15 lines +emit — function, 96 lines +write — function, 10 lines +docgen.lab.pg_probe — 150 lines +probe — function, 30 lines +_simplify — function, 3 lines +main — function, 25 lines +docgen.notebook.spec — 264 lines +_step — function, 4 lines +from_ir — function, 108 lines +_order — function, 5 lines +scaffold — function, 20 lines +merge — function, 58 lines +load — function, 2 lines +dump — function, 5 lines docgen -docgen -docgen.emitters -docgen.emitters -docgen.cli -docgen.cli -docgen.book -docgen.extractors -docgen.extractors.python -docgen.ir -docgen.ops -docgen.style -(root) -docgen.lab -docgen.notebook -selftest +docgen +docgen.cli +docgen.cli +docgen.emitters +docgen.emitters +docgen.book +docgen.extractors +docgen.extractors +docgen.extractors.python +docgen.ir +docgen.ops +docgen.ops +docgen.style +(root) +docgen.emitters.minisite +docgen.lab +docgen.notebook +selftest book style reference @@ -451,58 +454,58 @@ emitters lab __main__ -ir -extractors -site -notebook -explore -dot -minimap -erd -docsite -index -markdown -paged -auto -emit -extract -run -view -scaffold -common -book -check -contract -validate -config -document -build -checks -larder -notes -code -usage -openapi -db -python -collect -resolve -validate -model -filter -pages -extract -tokens -docgen -pg_probe -spec - -module - -class - -interface - -function -55 files · 13,028 lines · 1px ≈ 2.0 lines +ir +extractors +emit +extract +run +view +scaffold +common +book +check +contract +validate +notebook +explore +dot +minimap +erd +minisite +index +markdown +paged +auto +config +document +build +checks +larder +notes +code +usage +openapi +db +python +collect +resolve +validate +model +filter +pages +extract +tokens +docgen +onepage +pg_probe +spec + +module + +class + +interface + +function +55 files · 13,050 lines · 1px ≈ 2.0 lines diff --git a/soleprint/atlas2/docgen/docs/index.html b/soleprint/atlas2/docgen/docs/index.html index 9931fb6..78b2969 100644 --- a/soleprint/atlas2/docgen/docs/index.html +++ b/soleprint/atlas2/docgen/docs/index.html @@ -78,7 +78,7 @@ docgen is the one answer. It reads the source rather than being told about it, so a diagram cannot drift from the thing it describes, and it separates what a graph is from how it looks so one extraction feeds - a diagram, an index, a notebook and a browsable site without being redone. + a diagram, an index, a notebook and a browsable minisite without being redone.

@@ -131,7 +131,7 @@ make check BOOK=out/book/mine
  larder   /path/to/repo — 45 files read, 2 failed, 12 packages
   book     312 nodes · 244 edges · 26 external · 8 artifacts
   ok       45 file(s) read produced 45 module(s)
-  open     out/book/mine/site/index.html
+ open out/book/mine/minisite/index.html

Underneath it is three commands that compose, and each still works on its own. @@ -151,7 +151,7 @@ python3 -m docgen emit auto view.json -o out/

make ir SRC=/path/to/repo OUT=out   # extract
 make explore OUT=out                # the two-pane navigator
-make site OUT=out                   # a docs site with a sidebar
+make minisite OUT=out               # a one-page site with a sidebar
 make self                           # docgen's book of soleprint, then check it

@@ -163,7 +163,7 @@ make self # docgen's book of soleprint

Your first project

- From nothing to a notebook and a site for a project of yours, with your own text + From nothing to a notebook and a minisite for a project of yours, with your own text in the right places. docgen lives in its own folder, and the project only gets one config file and, later, a folder of notes.

@@ -195,8 +195,8 @@ ext = [".cs"] [emit.notebook] output = "../docs_out/orders_service_notebook" -[emit.site] -output = "../docs_out/orders_service_site" +[emit.minisite] +output = "../docs_out/orders_service_minisite"

Paths are relative to this file. Keep the outputs outside the source tree. See @@ -231,7 +231,7 @@ python3 -m docgen scaffold docgen.toml # or: write an e

Pick a spot and write markdown into notes/<book>/<spot>.md, for example notes/code/overview.md above the overview page. Rebuild - and it's there, in the notebook and on the site. Stubs you leave empty add + and it's there, in the notebook and on the minisite. Stubs you leave empty add nothing.

@@ -474,7 +474,7 @@ python3 -m docgen scaffold docgen.toml # or: write an e ├── notebook.ipynb the sequence; first and last cells are the measures ├── overlay.json hand-written, optional, re-applied every build ├── checks.py this book's own assertions — optional -└── site/ the web output, both measures at the top +└── minisite/ the web output, both measures at the top
make book SRC=../station BOOK=out/book/station
 make check BOOK=out/book/station
@@ -726,7 +726,7 @@ python3 -m docgen view ir.json --shape # what will this erdSVG, written directlya schema, as cards minimapSVG, written directlywhat is where, at a glance notebook.ipynba runnable walkthrough - sitea static docs sitereading + minisitea static docs sitereading explorea two-pane navigatorfinding your way autowhichever of the above fitsnot having to choose @@ -821,18 +821,18 @@ python3 -m docgen view ir.json --shape # what will this

Measured on soleprint, whose module graph rendered at 14:1 as one picture: 69 - pages, and at the site's 800px column the widest flagged page is 988px. + pages, and at the minisite's 800px column the widest flagged page is 988px. Schemas page differently: cards in columns capped to the width, grouped by tables joined by foreign keys, so a schema grows downward instead of sideways.

Which pages exist doesn't depend on width, only how each is laid out - does. A notebook column and a site column get the same pages, which is what lets + does. A notebook column and a minisite column get the same pages, which is what lets a note filed under a page land in the same place in both.
-

Clicking through, on the site

+

Clicking through, on the minisite

Every page is its own HTML file with the diagram inline, not in an @@ -978,7 +978,7 @@ python3 -m docgen emit notebook ir.json --overlay overlay.json -o walkthrough.ip To put text above a page, create the file named after it. No schema, no JSON, no ids to look up. That's something a person or a model can do without reading anything first. Local images in a note are embedded: as a cell attachment in the - notebook, as a data URI on the site. + notebook, as a data URI on the minisite.

make scaffold CONFIG=docgen.toml      # an empty stub for every spot, never overwriting
@@ -1129,10 +1129,10 @@ make doctor - - - - + + + +
contextchecksskipped
in the repo, synced346—
copied out, bare python3329tree-sitter, OpenAPI, the in-place case
copied out, synced338OpenAPI, the in-place case
copied out, synced, DOCGEN_REFERENCE set345
in the repo, synced348—
copied out, bare python3331tree-sitter, OpenAPI, the in-place case
copied out, synced340OpenAPI, the in-place case
copied out, synced, DOCGEN_REFERENCE set347 the in-place case — correctly, there is no repo above
@@ -1214,7 +1214,7 @@ python3 -m docgen run docgen.toml --list # resolved paths
A rebuild replaces the previous build, and nothing else. Before writing, a book removes exactly what a build writes — book.json, - notebook.ipynb, steps/, site/, + notebook.ipynb, steps/, minisite/, explore/ — and only from a directory that already holds a book.json. Without it a graph that is now graph.md kept its old graph.svg, unlisted in the ledger and still on the page. @@ -1262,14 +1262,14 @@ drop_builtins = true output = "../docs_out/orders_api_notebook" theme = "lucid" -[emit.site] -output = "../docs_out/orders_api_site" +[emit.minisite] +output = "../docs_out/orders_api_minisite" width = 800

Each [extract.*] table is a book, and a book is a part of every output rather than an output of its own. Each [emit.*] table - is an output made of all of them: one notebook and one site, each with a part + is an output made of all of them: one notebook and one minisite, each with a part per book. Several sources of one kind use [[extract.code]] with a name each. [ops] applies to every book's view before paging. @@ -1326,7 +1326,7 @@ width = 800 make indexmarkdown index and sidebar JSON make minimapwhat is where, read from the colours make explorethe two-pane navigator - make sitea self-contained docs site + make minisitea self-contained one-page site make selfdocgen's book of soleprint, then check it @@ -1381,7 +1381,7 @@ python3 -m docgen emit dot view.json -o graph.svg --theme lucid python3 -m docgen emit erd ir.json -o schema.svg python3 -m docgen emit minimap ir.json -o map.svg --scale 0.5 python3 -m docgen emit notebook ir.json -o book.ipynb --overlay overlay.json -python3 -m docgen emit site view.json -o site/ +python3 -m docgen emit minisite view.json -o minisite/ python3 -m docgen emit explore ir.json -o explore/

Where the command line lives

@@ -1407,7 +1407,7 @@ python3 -m docgen emit explore ir.json -o explore/ A command reports an expected failure by raising, and cli.main turns it into the only exit path: one Error: line on stderr, exit 1, never a traceback. Doing that split also surfaced a third copy of "which drawing - does this graph want" — in the auto command, the site + does this graph want" — in the auto command, the minisite command and the book — which is now emitters.auto.draw(), returning content and leaving the file name to the caller.

@@ -1473,14 +1473,14 @@ make lock # after editing pyproject commandasks aboutfails? make doctorthe machine — what is installed never; it reports - make checkdocgen — 346 checks + make checkdocgen — 348 checks exit 1 make check BOOK=<dir>that one book, or a project's document exit 1

- All 346 after make sync, 331 with nothing optional installed — the + All 348 after make sync, 333 with nothing optional installed — the suite skips rather than fails when tree-sitter, lxml or the OpenAPI reader is absent. See standalone for the counts outside the repo. Among them, two that keep this page's structure true: nothing outside diff --git a/soleprint/atlas2/docgen/docs/models.md b/soleprint/atlas2/docgen/docs/models.md index d92e257..142df0e 100644 --- a/soleprint/atlas2/docgen/docs/models.md +++ b/soleprint/atlas2/docgen/docs/models.md @@ -68,8 +68,8 @@ drop_builtins = true output = "../docs_out/orders_service_notebook" theme = "lucid" -[emit.site] -output = "../docs_out/orders_service_site" +[emit.minisite] +output = "../docs_out/orders_service_minisite" ``` ### `[project]` @@ -112,8 +112,8 @@ name = "frontend" root = "web/src" ext = [".ts", ".tsx"] -[emit.site] -output = "../docs_out/storefront_site" +[emit.minisite] +output = "../docs_out/storefront_minisite" ``` ### `[ops]`: applied to every book before drawing @@ -131,14 +131,15 @@ Kinds: `module`, `class`, `interface`, `function`, `external`, `table`, `column` ### `[emit.]`: the outputs -The outputs are `notebook` and `site`, nothing else. +The outputs are `notebook` and `minisite`, nothing else. `site` is the old name of +`minisite` and is refused. | key | required | value | |---|---|---| | `output` | yes | a directory. A notebook output may also be a path ending in `.ipynb` | | `theme` | no | `"dark"` (default) or `"lucid"` (light, for print) | | `style` | no | `"lucid"` (default) | -| `width` | no | pixels a diagram page must fit; default 960 for a notebook, 800 for a site | +| `width` | no | pixels a diagram page must fit; default 960 for a notebook, 800 for a minisite | --- @@ -174,7 +175,7 @@ A book's own value replaces the default for that key. Values are never merged. ## Notes A note is a markdown file. docgen puts its content directly above the spot it is named -after, in both the notebook and the site. Its path is: +after, in both the notebook and the minisite. Its path is: ``` /_intro.md top of the whole document @@ -250,7 +251,8 @@ The person running docgen pastes the errors back. Each one says what to change: | `docgen reads a schema dump and never connects` | remove `url`; use `schema = "path/to/schema.json"` | | `no grammar for .sh` | remove those extensions from `ext` | | `no reader named 'x'` | use one of `python`, `code`, `db`, `openapi`, `usage` | -| `no output named 'x'` | use `notebook` or `site` | +| `no output named 'x'` | use `notebook` or `minisite` | +| `is now [emit.…] — rename the table` | rename `[emit.site]` to `[emit.minisite]`; nothing else changes | | `is inside the tree it reads` | move `output` or `build` outside the source directory | | `needs a name when there are several` | give each `[[extract.x]]` table a different `name` | | `must name exactly one source` | a `[[book]]` needs exactly one of `root`, `schema`, `openapi`, `har` | diff --git a/soleprint/atlas2/docgen/emitters/auto.py b/soleprint/atlas2/docgen/emitters/auto.py index b7e8aa2..8e5764e 100644 --- a/soleprint/atlas2/docgen/emitters/auto.py +++ b/soleprint/atlas2/docgen/emitters/auto.py @@ -11,7 +11,7 @@ because that *is* the right artifact for a flat list of peers. ## One function, three callers This branch — erd, or index, or dot through Graphviz — used to be written out -three times: in the `auto` command, in the `site` command choosing its picture, +three times: in the `auto` command, in the `minisite` command choosing its picture, and in the book choosing its graph step. Three copies of "which drawing does this graph want" is three chances for them to disagree about the answer, so it lives here and returns content rather than writing it. Where the file goes, and what @@ -37,7 +37,7 @@ def draw(ir: dict, style, *, force: str | None = None) -> dict: "why": why this emitter, or why nothing was drawn} Never raises for a missing Graphviz. A layered graph on a machine without - `dot` is a normal state — the book records the step as skipped and the site + `dot` is a normal state — the book records the step as skipped and the minisite goes text-only — so it is reported in `why` with `content` None. """ verdict = classify(ir) diff --git a/soleprint/atlas2/docgen/emitters/dot.py b/soleprint/atlas2/docgen/emitters/dot.py index bc4915b..9bde39d 100644 --- a/soleprint/atlas2/docgen/emitters/dot.py +++ b/soleprint/atlas2/docgen/emitters/dot.py @@ -78,7 +78,7 @@ def _node_attrs(node, rule: dict, style, links: dict | None = None) -> dict: attrs = node.get("attrs") or {} if links and node["id"] in links: # A link the caller supplied wins over the source anchor: on a paginated - # site a box is a way into its own page, which is worth more than the + # minisite a box is a way into its own page, which is worth more than the # file it came from. a["href"] = links[node["id"]] a["tooltip"] = attrs.get("doc") or f"open {node['id']}" @@ -100,7 +100,7 @@ def emit(ir: dict, style, *, max_depth: int | None = None, `links` maps node ids to URLs and becomes each box's `href` in the SVG. Passed in rather than read from the IR, because where a box leads is a fact - about the output — a site page, a notebook anchor — and the IR is the same + about the output — a minisite page, a notebook anchor — and the IR is the same for every output. Same rule that keeps colour out of it. """ nodes = {n["id"]: n for n in ir["nodes"]} diff --git a/soleprint/atlas2/docgen/emitters/markdown.py b/soleprint/atlas2/docgen/emitters/markdown.py index 767cd78..c70691c 100644 --- a/soleprint/atlas2/docgen/emitters/markdown.py +++ b/soleprint/atlas2/docgen/emitters/markdown.py @@ -1,7 +1,7 @@ """ -Markdown -> HTML, for notes on the site. Stdlib only, and deliberately small. +Markdown -> HTML, for notes on the minisite. Stdlib only, and deliberately small. -A notebook renders markdown itself, so notes go into it as written. The site has +A notebook renders markdown itself, so notes go into it as written. The minisite has no renderer, and adding a dependency to turn a few paragraphs into HTML would break the rule that the structural path is the stdlib. So this covers what notes are actually written with: diff --git a/soleprint/atlas2/docgen/emitters/docsite.py b/soleprint/atlas2/docgen/emitters/minisite/__init__.py similarity index 91% rename from soleprint/atlas2/docgen/emitters/docsite.py rename to soleprint/atlas2/docgen/emitters/minisite/__init__.py index cc902dc..d0b7e59 100644 --- a/soleprint/atlas2/docgen/emitters/docsite.py +++ b/soleprint/atlas2/docgen/emitters/minisite/__init__.py @@ -1,9 +1,9 @@ """ -A document's site: an index of books, and every book as pages you click through. +The minisite: a document's index of books, and every book as pages you click through. - site/ + minisite/ ├── index.html every book, with what came in and what came out - ├── site.css viewer.html + ├── minisite.css viewer.html └── / ├── overview.html the book's top page ├── .html one subsystem each; its boxes open the next level @@ -12,7 +12,7 @@ A document's site: an index of books, and every book as pages you click through. ## Inline, so the boxes are links -The single-page site put its diagram in an ``, and an image swallows every +The single-page reference (`onepage.py`) put its diagram in an ``, and an image swallows every click. Here the SVG is inlined, so a box that stands for a subsystem opens that subsystem's page, a box for a module opens its section of the reference page, and a context box — something outside this subsystem — opens its own branch. @@ -33,10 +33,10 @@ never heard of a book's extractor, and this one has not either. from html import escape from pathlib import Path -from .markdown import to_html -from .paged import inline -from .site import CONTENT_W, CSS, SIDEBAR_W, VIEWER, _fill, _ledger, _slots -from .site import emit as reference_page +from ..markdown import to_html +from ..paged import inline +from .onepage import CONTENT_W, CSS, SIDEBAR_W, VIEWER, _fill, _ledger, _slots +from .onepage import emit as reference_page CONTENT_WIDTH = CONTENT_W @@ -75,7 +75,7 @@ def _note(note, cls="note") -> str: def _missing(failed: dict | None) -> str: """Books that were meant to be here and are not. Above the ones that are, - because a reader who does not see this has no way to know the site is short.""" + because a reader who does not see this has no way to know the minisite is short.""" if not failed: return "" items = "".join(f"

  • {escape(name)} — {escape(why)}
  • " @@ -116,7 +116,7 @@ def _page(title: str, book: dict, page: dict, svg: str | None, pages: list[dict] else: crumbs.append(f'{escape(p["title"])}') - from ..book.document import caption # noqa: F401 - kept out of module import time + from ...book.document import caption # noqa: F401 - kept out of module import time cap = caption(page) warn = " warn" if page.get("too_wide") else "" if svg is not None: @@ -144,7 +144,7 @@ def _page(title: str, book: dict, page: dict, svg: str | None, pages: list[dict] {escape(page["title"])} — {escape(b.slug)} — {escape(doc_title)} - +
    @@ -174,7 +174,7 @@ def _page(title: str, book: dict, page: dict, svg: str | None, pages: list[dict] def write(out_dir, style, *, title: str, books: list[dict], intro=None, end=None, failed: dict | None = None) -> list[Path]: - """Write the site. Returns every file written, for the output manifest. + """Write the minisite. Returns every file written, for the output manifest. `books` is a list of:: @@ -193,7 +193,7 @@ def write(out_dir, style, *, title: str, books: list[dict], intro=None, end=None path.write_text(text) written.append(path) - put(out_dir / "site.css", + put(out_dir / "minisite.css", _fill(CSS.replace("__SIDEBAR__", str(SIDEBAR_W)).replace("__CONTENT__", str(CONTENT_W)), values)) put(out_dir / "viewer.html", _fill(VIEWER.replace("__TITLE__", escape(title)), values)) @@ -209,10 +209,10 @@ def write(out_dir, style, *, title: str, books: list[dict], intro=None, end=None if svg is not None: put(book_dir / f"{page['slug']}.svg", svg) - # The reference page: the single-page site as it was, one per book, where + # The reference page: the single-page `onepage` as it was, one per book, where # a module box on any page opens its own section. ref = reference_page(b.view, style, title=f"{b.slug} — reference")["index.html"] - ref = ref.replace('href="site.css"', 'href="../site.css"') + ref = ref.replace('href="minisite.css"', 'href="../minisite.css"') put(book_dir / "reference.html", ref) explore = b.out / "explore" @@ -246,7 +246,7 @@ def write(out_dir, style, *, title: str, books: list[dict], intro=None, end=None {escape(title)} - +
    diff --git a/soleprint/atlas2/docgen/emitters/site.py b/soleprint/atlas2/docgen/emitters/minisite/onepage.py similarity index 98% rename from soleprint/atlas2/docgen/emitters/site.py rename to soleprint/atlas2/docgen/emitters/minisite/onepage.py index e48c933..aedcccc 100644 --- a/soleprint/atlas2/docgen/emitters/site.py +++ b/soleprint/atlas2/docgen/emitters/minisite/onepage.py @@ -1,5 +1,7 @@ """ -IR -> a self-contained documentation site: sidebar, content, graph viewer. +IR -> one self-contained page: sidebar, content, graph viewer. + +The minisite's per-book reference page, and `emit minisite` on a bare IR. Not invented here. Five demos under `semester/` already converged on the same two files, and this generates that arrangement rather than a sixth variant: @@ -29,7 +31,7 @@ are looking at. A click that moved the mouse is a drag and does not toggle. ## Colours Baked from the same style slots as every diagram, so the page and the graph on -it match by construction. `--theme lucid` produces a light site and a light +it match by construction. `--theme lucid` produces a light page and a light diagram together; nothing has to be kept in sync by hand. Self-contained and offline: no CDN, no build step, opens over `file://`. @@ -316,7 +318,7 @@ body { def _ledger(book: dict) -> str: """The two measures, and the gap between them if there is one. - This is the whole reason the site is the book's last step rather than just + This is the whole reason the minisite is the book's last step rather than just another emitter: it is the one artifact somebody definitely opens, so it is where "45 of 47 files" has to appear. A diagram cannot say it, and a log nobody reads does not count as having said it. @@ -435,9 +437,9 @@ def emit(ir: dict, style, *, graph: str | None = None, title: str = "", `book` is a book ledger (`book/__init__.py`). When present the page opens with both measures — what went in, what came out — because a page that shows only the result is the thing the measure exists to correct. - Optional, so the site emitter still works on a bare IR. + Optional, so the page still works on a bare IR. """ - from .index import to_sidebar + from ..index import to_sidebar meta = ir.get("meta", {}) name = title or meta.get("root", "docs") @@ -477,7 +479,7 @@ def emit(ir: dict, style, *, graph: str | None = None, title: str = "", {escape(name)} - +
    @@ -519,7 +521,7 @@ document.querySelectorAll('h2[id], h3[id]').forEach(function (h) {{ obs.observe( return { "index.html": index, "viewer.html": _fill(VIEWER.replace("__TITLE__", escape(name)), values), - "site.css": _fill( + "minisite.css": _fill( CSS.replace("__SIDEBAR__", str(SIDEBAR_W)).replace("__CONTENT__", str(CONTENT_W)), values, ), diff --git a/soleprint/atlas2/docgen/emitters/paged.py b/soleprint/atlas2/docgen/emitters/paged.py index 92ba6f1..b942541 100644 --- a/soleprint/atlas2/docgen/emitters/paged.py +++ b/soleprint/atlas2/docgen/emitters/paged.py @@ -17,7 +17,7 @@ page records `measured: False` so nobody mistakes one for the other. Graphviz and the ERD emitter both write sizes in points, and a browser draws a point as 4/3 of a CSS pixel. Budgets here are pixels, because the column they -have to fit — a notebook cell, a site's content column — is sized in pixels. +have to fit — a notebook cell, a minisite's content column — is sized in pixels. """ import re @@ -25,8 +25,8 @@ import re PT_TO_PX = 4 / 3 # Budgets for the outputs docgen writes. A notebook cell in JupyterLab or VS Code -# is a little under a thousand pixels at a normal window size; the site's content -# column is set by `site.CONTENT_W`. +# is a little under a thousand pixels at a normal window size; the minisite's +# content column is set by `minisite.CONTENT_W`. NOTEBOOK_WIDTH = 960 @@ -72,7 +72,7 @@ def fits_for(style, width: int): def links_for(pages: list[dict], page: dict, url) -> dict: """{box id on this page: url of the page that box opens}. - `url(target_page)` builds the address, so the site and anything else that + `url(target_page)` builds the address, so the minisite and anything else that can follow a link decide their own scheme. Context boxes link too, when their branch has a page of its own — that is how a reader crosses to a sibling. """ diff --git a/soleprint/atlas2/docgen/ops/pages.py b/soleprint/atlas2/docgen/ops/pages.py index 22dc851..469cba2 100644 --- a/soleprint/atlas2/docgen/ops/pages.py +++ b/soleprint/atlas2/docgen/ops/pages.py @@ -12,7 +12,7 @@ estimated from node counts is wrong the moment the labels are long. **Which pages exist does not depend on width** — only how each one is laid out does. So the two are separate calls: the page ids a note is filed under are the -same for a notebook column and a site column, and listing them needs no +same for a notebook column and a minisite column, and listing them needs no renderer at all. ## By structure, never by slicing @@ -24,7 +24,7 @@ nothing on its own. A page here is a subsystem: └── station one box per child of `station` └── station.tools one box per child of `station.tools`, and so on -Clicking a box — on the site — or following the index — in a notebook — moves +Clicking a box — on the minisite — or following the index — in a notebook — moves down a level. Every page is a real graph: the boxes are the scope's children, and anything outside the scope that they touch appears as a **context** box, collapsed to the branch it sits on, so a page still says what its subsystem @@ -203,7 +203,7 @@ def paginate(view: dict, *, max_depth: int = 6) -> list[dict]: `options` and `too_wide` are placeholders until `layout()` fills them. in reading order — a page is followed by its own children, depth first — so - a notebook can emit them in sequence and a site can build its tree from + a notebook can emit them in sequence and a minisite can build its tree from `parent` and `children`. """ pages: list[dict] = [] diff --git a/soleprint/atlas2/docgen/selftest.py b/soleprint/atlas2/docgen/selftest.py index 9575d56..86611ae 100644 --- a/soleprint/atlas2/docgen/selftest.py +++ b/soleprint/atlas2/docgen/selftest.py @@ -46,7 +46,7 @@ index_mod = __import__(f"{PKG}.emitters.index", fromlist=["*"]) ops_mod = __import__(f"{PKG}.ops", fromlist=["*"]) erd_mod = __import__(f"{PKG}.emitters.erd", fromlist=["*"]) nb_mod = __import__(f"{PKG}.emitters.notebook", fromlist=["*"]) -site_mod = __import__(f"{PKG}.emitters.site", fromlist=["*"]) +site_mod = __import__(f"{PKG}.emitters.minisite.onepage", fromlist=["*"]) mm_mod = __import__(f"{PKG}.emitters.minimap", fromlist=["*"]) exp_mod = __import__(f"{PKG}.emitters.explore", fromlist=["*"]) spec_mod = __import__(f"{PKG}.notebook", fromlist=["*"]) @@ -1284,18 +1284,18 @@ check("every verdict carries options", "options" in ops_mod.classify(ir)) # -------------------------------------------------------------------------- -print("\n11. the docs site") +print("\n11. the minisite's one page") # Not invented here: five demos under semester/ carry the same viewer, differing # only in comments and one background colour. This generates that arrangement # rather than a sixth copy — and adds the 1:1 toggle none of them has. -site_dir = ROOT.parent / "site" +site_dir = ROOT.parent / "minisite" files = site_mod.write(ops_mod.overview(ir), lucid, site_dir, graph="graph.svg", title="fx") names = {f.name for f in files} -check("it writes the three files", names == {"index.html", "viewer.html", "site.css"}, str(names)) +check("it writes the three files", names == {"index.html", "viewer.html", "minisite.css"}, str(names)) index_html = (site_dir / "index.html").read_text() -css = (site_dir / "site.css").read_text() +css = (site_dir / "minisite.css").read_text() viewer = (site_dir / "viewer.html").read_text() check( @@ -1316,8 +1316,8 @@ check( light = site_mod.emit(ops_mod.overview(ir), print_theme, graph="graph.svg") check( "a light theme gives a light page", - print_theme.slot("surface-0") in light["site.css"] - and lucid.slot("surface-0") not in light["site.css"], + print_theme.slot("surface-0") in light["minisite.css"] + and lucid.slot("surface-0") not in light["minisite.css"], "the page and the diagram on it move together", ) check( @@ -1766,11 +1766,11 @@ def _books(): ran, failure = checks_mod._run_cells(nb["cells"], out) check(f"its {ran} code cells run from the book directory", failure is None, failure or "") - html = (out / "site" / "index.html").read_text() + html = (out / "minisite" / "index.html").read_text() check( "the web output shows both ends", "what came in" in html and "what came out" in html, - "the site is the last step because it is the artifact somebody opens", + "the minisite is the last step because it is the artifact somebody opens", ) check( "and admits when the book is incomplete", @@ -1783,7 +1783,7 @@ def _books(): again = Path(tmp.name) / "book-out-2" build_mod.run("python", fixture, again, slug="fixture", quiet=True) differs = [ - name for name in ("book.json", "notebook.ipynb", "steps/ir.json", "site/index.html") + name for name in ("book.json", "notebook.ipynb", "steps/ir.json", "minisite/index.html") if (out / name).read_bytes() != (again / name).read_bytes() ] check("the same larder builds the same bytes", not differs, f"differ: {differs}") @@ -2094,9 +2094,12 @@ def _layout(): and "Traceback" not in bad.stderr and bad.stderr.count("\n") == 1, f"exit {bad.returncode}: {bad.stderr[:120]!r}", ) + old = run("emit", "site") + check("`emit site` names its new name, `emit minisite`", + old.returncode == 1 and "is now emit minisite" in old.stderr, old.stderr[:120]) # The structure-picks-the-drawing branch used to be written three times — - # the `auto` command, the `site` command, the book. Now it is `draw()`, and + # the `auto` command, the `minisite` command, the book. Now it is `draw()`, and # the book reaching past it to the concrete emitters would be the first copy. # Parsed, not grepped, for the reason section 2 gives: the docstring naming # `emitters.dot` is prose, and the first version of this check failed on it. @@ -2266,7 +2269,7 @@ def _runfiles(): check( "a rebuild removes the previous build's outputs", again["app"]["ok"] and not (app / "steps" / "stale.svg").exists(), - "a stale graph.svg would go on showing in the site, unlisted in the ledger", + "a stale graph.svg would go on showing in the minisite, unlisted in the ledger", ) check("...and keeps the hand-written checks.py", (app / "checks.py").exists()) @@ -2381,7 +2384,7 @@ def _pages(): and p["children"]], ) # Which pages exist must not depend on width — notes are filed by page id, - # and a note has to land in the same place in a notebook and on a site. + # and a note has to land in the same place in a notebook and on a minisite. check( "which pages exist does not depend on width", [p["id"] for p in pages_mod.layout(structure, lambda ir, o: False)] @@ -2406,7 +2409,7 @@ def _pages(): if px > 800 and not p["too_wide"]: over.append(f"{p['id']} {px:.0f}px") check("no page is wider than its budget unless it says so", not over, "; ".join(over)) - # Links are the output's, never the IR's: a site passes them, and then a + # Links are the output's, never the IR's: a minisite passes them, and then a # relative source path — a dead link on a web page — must not survive. page = next(p for p in laid if p["children"]) links = paged.links_for(laid, page, lambda t: f"{t['slug']}.html") @@ -2546,15 +2549,15 @@ def _documents(): build_mod.run("python", src, out, slug="app", notes=notes, quiet=True) check("the same sources and notes build the same notebook", first == (out / "notebook.ipynb").read_bytes()) - # -- the site: drill-down -------------------------------------------------- - site = out / "site" + # -- the minisite: drill-down ---------------------------------------------- + site = out / "minisite" page_files = sorted((site / "app").glob("*.html")) broken = [] for f in page_files: for href in re.findall(r'href="([^"#?]+)', f.read_text()): if not href.startswith(("http:", "https:")) and not (f.parent / href).exists(): broken.append(f"{f.name} -> {href}") - check("every link on every site page opens something", not broken, broken[:5]) + check("every link on every minisite page opens something", not broken, broken[:5]) overview_html = (site / "app" / "overview.html").read_text() check( "a page's diagram is inline, so its boxes can be clicked", @@ -2569,15 +2572,15 @@ def _documents(): 'href="overview.html"' in child_html.split('class="crumbs"')[1].split("
    ")[0], ) check("a page has a fit / 1:1 control", 'data-size="actual"' in overview_html) - check("the site renders the note above the diagram", + check("the minisite renders the note above the diagram", overview_html.index("Written by hand") < overview_html.index('class="figbar"')) # Manifests: a rebuild removes what the last one wrote, and nothing else. - project_out = base / "project-site" + project_out = base / "project-minisite" doc = doc_mod.Document( name="p", title="P", build=base / "p-build", notes=None, parts=[doc_mod.Part(name="app", kind="python", source=src, out=base / "p-build" / "app")], - outputs=[doc_mod.Output("site", project_out)]) + outputs=[doc_mod.Output("minisite", project_out)]) doc_mod.build(doc) (project_out / "app" / "stale.html").write_text("left by a previous build") manifest = json.loads((project_out / ".docgen-output.json").read_text()) @@ -2592,19 +2595,19 @@ def _documents(): # One book that cannot be built must not cost the document — and the document # has to say it is short, where a reader will see it, not only in a terminal. (base / "broken.har").write_text("not a recording") - partial_site = base / "partial-site" + partial_site = base / "partial-minisite" partial = doc_mod.Document( name="partial", title="Partial", build=base / "partial-build", notes=None, parts=[doc_mod.Part(name="bad", kind="usage", source=base / "broken.har", out=base / "partial-build" / "bad"), doc_mod.Part(name="app", kind="python", source=src, out=base / "partial-build" / "app")], - outputs=[doc_mod.Output("site", partial_site), + outputs=[doc_mod.Output("minisite", partial_site), doc_mod.Output("notebook", base / "partial.ipynb")]) doc_mod.build(partial) check("a book that fails does not stop the others", [b.slug for b in partial.books] == ["app"] and "bad" in partial.failed) - check("the site says the document is incomplete", + check("the minisite says the document is incomplete", "This document is incomplete" in (partial_site / "index.html").read_text()) check("...and so does the notebook", "This document is incomplete" in (base / "partial.ipynb").read_text()) @@ -2636,7 +2639,7 @@ def _projects(): project, problems = load( '[project]\nname = "p"\n\n[extract.python]\nroot = "src"\n\n' '[extract.db]\nschema = "shop.json"\n\n[ops]\ndrop_stdlib = true\n\n' - '[emit.notebook]\noutput = "out/nb"\n\n[emit.site]\noutput = "out/site"\nwidth = 700\n') + '[emit.notebook]\noutput = "out/nb"\n\n[emit.minisite]\noutput = "out/minisite"\nwidth = 700\n') check("a project file loads", isinstance(project, cfg.ProjectFile), problems) if project is None: return @@ -2644,10 +2647,10 @@ def _projects(): check( "each [extract.*] is a book, each [emit.*] an output of all of them", [p.name for p in doc.parts] == ["python", "db"] - and sorted(o.emitter for o in doc.outputs) == ["notebook", "site"], + and sorted(o.emitter for o in doc.outputs) == ["minisite", "notebook"], ) check("[ops] applies to every book", all(p.ops.get("drop_stdlib") for p in doc.parts)) - check("an output's width is kept", next(o for o in doc.outputs if o.emitter == "site").width == 700) + check("an output's width is kept", next(o for o in doc.outputs if o.emitter == "minisite").width == 700) books_file, _ = load('[[book]]\nname = "a"\nroot = "src"\n', "books.toml") check("a [[book]] list still loads as it did", isinstance(books_file, cfg.RunFile)) @@ -2661,7 +2664,7 @@ def _projects(): '[project]\nname = "p"\n\n' '[extract.db]\nurl = "postgresql://user:hunter2@localhost:5432/app"\n\n' '[extract.code]\nroot = "src"\next = [".sh", ".yaml", ".sql"]\n\n' - '[extract.seed]\nroot = "src"\n\n[emit.site]\noutput = "out"\n', "refused.toml") + '[extract.seed]\nroot = "src"\n\n[emit.minisite]\noutput = "out"\n', "refused.toml") text = "\n".join(refused) check("a database url is refused, pointing at modelgen from-db", "never connects" in text and "modelgen from-db" in text, refused) @@ -2670,8 +2673,13 @@ def _projects(): "no grammar for .sh, .yaml, .sql" in text and ".cs" in text) check("an unknown reader is refused, naming the readers", "no reader named 'seed'" in text) _, inside = load('[project]\nname = "p"\n[extract.python]\nroot = "src"\n' - '[emit.site]\noutput = "src/site"\n', "inside.toml") + '[emit.minisite]\noutput = "src/minisite"\n', "inside.toml") check("an output inside a tree it reads is refused", any("inside the tree" in p for p in inside), inside) + _, renamed = load('[project]\nname = "p"\n[extract.python]\nroot = "src"\n' + '[emit.site]\noutput = "out/site"\n', "renamed.toml") + check("the old [emit.site] is refused with its new name, not as unknown", + any("is now [emit.minisite]" in p for p in renamed) + and not any("no output named" in p for p in renamed), renamed) example = cfg.load(HERE / "docgen.project.example.toml") check("the shipped project example loads", diff --git a/soleprint/atlas2/docgen/viewer_test.js b/soleprint/atlas2/docgen/viewer_test.js index 4ed571c..4707a55 100644 --- a/soleprint/atlas2/docgen/viewer_test.js +++ b/soleprint/atlas2/docgen/viewer_test.js @@ -1,6 +1,6 @@ // Drive the generated viewer's logic under a stub DOM and assert the toggle. const fs = require('fs'); -const html = fs.readFileSync(process.argv[2] || '/tmp/site/viewer.html', 'utf8'); +const html = fs.readFileSync(process.argv[2] || '/tmp/minisite/viewer.html', 'utf8'); const script = html.split('')[0]; const handlers = {};