Files
funkpower c4e1fb9c02 drop the parity harness, keep what it argued
The harness compared these tools against the code they replaced — Python
imported from book-pipeline, podcast-pipeline and knowledge-mcp, and
JavaScript copied out of the podcast media server and indexer, each pinned to
a commit. All of it has since been deleted, so the live half cannot run and
the golden half pins answers against a source nobody can consult.

What was worth keeping was never the comparison. `KNOWN.md` argued, at
length, why a dozen of these tools deliberately do something a reader would
not expect: why pdfgutter measures the crop box throughout, why avplan finds
the encoder rather than reading one out of the environment, why mdscrub will
not manufacture a page boundary. Those arguments are about this code and
stand on their own, so they are now `docs/decisions.md`, rewritten to say
what each tool does and why rather than what it does differently.

Binding coverage is unaffected: the bindings carry 24 tests of their own, a
node smoke test against the built package, and a typecheck.
2026-09-21 07:25:10 -04:00

75 lines
2.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""Check that every link between the markdown files goes somewhere.
Documentation that links to a page that has been renamed is worse than
documentation that does not link at all, because the reader trusts it. Run
from the repository root:
python3 tools/check-links.py
"""
import pathlib
import re
import sys
LINK = re.compile(r"\[[^\]]*\]\(([^)]+)\)")
def prose(text: str) -> str:
"""The document with its fenced code blocks taken out.
An example that happens to contain a link is an example, not a link.
"""
out, fenced = [], False
for line in text.split("\n"):
if line.startswith("```"):
fenced = not fenced
continue
if not fenced:
out.append(line)
return "\n".join(out)
def anchors(text: str) -> set[str]:
"""The headings of a document, as the fragments that reach them."""
found = set()
for line in prose(text).split("\n"):
if line.startswith("#"):
title = line.lstrip("#").strip().lower()
found.add(re.sub(r"[^a-z0-9 -]", "", title).replace(" ", "-"))
return found
def main() -> int:
root = pathlib.Path(".").resolve()
# Fixtures are not documentation: a test case is deliberately malformed
# markdown, and a link in one is part of what is being tested.
skip = {"target", "cases", "golden"}
files = sorted(
path
for path in root.rglob("*.md")
if skip.isdisjoint(path.parts) and not path.name.startswith(".")
)
headings = {path: anchors(path.read_text(encoding="utf-8")) for path in files}
broken = []
for path in files:
for target in LINK.findall(prose(path.read_text(encoding="utf-8"))):
if target.startswith(("http://", "https://", "mailto:")):
continue
where, _, fragment = target.partition("#")
dest = (path.parent / where).resolve() if where else path
if not dest.exists():
broken.append(f"{path.relative_to(root)} -> {target}: no such file")
elif fragment and dest in headings and fragment not in headings[dest]:
broken.append(f"{path.relative_to(root)} -> {target}: no such heading")
for line in broken:
print(f"broken link: {line}", file=sys.stderr)
print(f"{len(files)} files, {len(broken)} broken links")
return 1 if broken else 0
if __name__ == "__main__":
raise SystemExit(main())