|
23 | 23 | ROOT = Path(__file__).parent.parent.parent |
24 | 24 |
|
25 | 25 |
|
| 26 | +def _missing_nav_pages(nav: list, docs_dir: Path) -> list[str]: |
| 27 | + """Collect nav page references that don't exist under the docs dir. |
| 28 | +
|
| 29 | + Zensical (0.0.48) ships a nav entry for a nonexistent page as a broken |
| 30 | + link without any diagnostic, even under --strict — MkDocs aborted the |
| 31 | + build. Validating here keeps that guarantee: the concrete config never |
| 32 | + leaves this script referencing a page that isn't there. |
| 33 | + """ |
| 34 | + missing: list[str] = [] |
| 35 | + for entry in nav: |
| 36 | + value = next(iter(entry.values())) if isinstance(entry, dict) else entry |
| 37 | + if isinstance(value, list): |
| 38 | + missing.extend(_missing_nav_pages(value, docs_dir)) |
| 39 | + elif not (docs_dir / value).is_file(): |
| 40 | + missing.append(value) |
| 41 | + return missing |
| 42 | + |
| 43 | + |
26 | 44 | def build_config(output: Path, site_dir: str | None = None) -> None: |
27 | 45 | config = yaml.safe_load((ROOT / "mkdocs.yml").read_text(encoding="utf-8")) |
28 | 46 |
|
29 | 47 | api_nav = gen_ref_pages.generate() |
| 48 | + if not api_nav: |
| 49 | + raise SystemExit("build_config: gen_ref_pages produced no API pages — did the src/ layout move?") |
30 | 50 | for entry in config["nav"]: |
31 | 51 | if isinstance(entry, dict) and "API Reference" in entry: |
32 | 52 | entry["API Reference"] = api_nav |
33 | 53 | break |
34 | 54 | else: |
35 | 55 | raise SystemExit("build_config: no 'API Reference' entry found in mkdocs.yml nav") |
36 | 56 |
|
| 57 | + if missing := _missing_nav_pages(config["nav"], ROOT / "docs"): |
| 58 | + raise SystemExit(f"build_config: nav references pages that don't exist under docs/: {missing}") |
| 59 | + |
37 | 60 | if site_dir is not None: |
38 | 61 | config["site_dir"] = site_dir |
39 | 62 |
|
|
0 commit comments