Fix the documented shape of projectMap's heading map - #18
Merged
Conversation
The README's "Inspecting a document" example showed `headings` as an array of paths -- `[["Meeting Notes"], ["Meeting Notes", "Action Items"]]` -- a shape no released version has produced. 1.x's `getDocumentMap` returned a flat `Record` keyed by `::`-joined strings; 2.0's `projectMap` returns a tree nested by containment. A reader following the example indexed into an array that is really an object, and the prose built on it was wrong too: the tree carries no levels, so there is no "length is the heading's level" and no `null` standing in for a skipped one. Rewrite the snippet and its prose against the real shape, point at `headingTreePaths` for turning the tree into addresses, and fix the same drifted copy in pages/how_to.md. Note the map's shape change in the 1.x migration section, since `getDocumentMap` users are the readers most likely to expect the old flat record. Add docs.map.test.ts alongside the existing docs.* tests: it reads the sample document out of README.md, asserts the projection matches the documented map (version hash included), and asserts the docs still quote that map verbatim -- so an engine change and a docs edit each fail a different assertion instead of silently drifting apart again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011UMMqb4R5YU17gjVPrhva8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
README § "Inspecting a document" documented
projectMap(buildModel(document))as returningheadingsas an array of paths:The engine returns a tree nested by containment. The prose on top of it was wrong in the same way — "each entry is an array whose length is that heading's level", "a
nullelement marks a skipped level" — and theversionhash shown (c23234) was not the hash of the sample document either.pages/how_to.md(a typedoc project document) carried the same drifted example.This shape was never real. 1.x's
getDocumentMapreturnedRecord<"A::B", { marker, content, level }>(seesrc/types.tsat629227e^); 2.0'sprojectMapreturns the containment tree. Neither ever produced an array of paths, so the documented example could not have worked in any released version.Evidence
Observed output, not read off the source — the README's own sample document, through the library and through the CLI:
The prose claims were checked the same way:
{}{"Meeting Notes":{"Action Items":{}}}# Onethen### Deep){"One":{"Deep":{}}}— no placeholder""(# Onethen##){"One":{"":{}}}{"Log":{"Monday":{}},"Log␣␣":{"Tuesday":{}}},blocks: ["abc","abc␣␣"]Guard against re-drift
src/tests/docs.map.test.ts(following the existingdocs.rename.test.ts/docs.whitespace.test.tsprecedent) reads the sample document out of README.md and asserts both directions:Plus the prose claims: leaf
{},headingTreePathsenumeration, every advertised path resolving throughreadTarget, skipped level, empty-heading key.Negative control — with the old documented values substituted, the assertions fail as intended:
npm test: 519 passed, 21 suites.tsc --noEmit: clean. No source change —src/is untouched apart from the new test, so there is no runtime behavior to regress.Where this could be worse than before
versionhash in the README is new exposure: editing the sample document now breaks a test. That is deliberate (the old hash was wrong and nothing caught it), and the failure is a one-line update with the message pointing at it.const document = ...from README.md could go stale if the snippet is restructured. It throws a named error explaining what moved rather than silently passing on a wrong document.getDocumentMapusers are the readers most likely to expect the flat record; drop it if you'd rather keep that section at two bullets.Honest gaps
src/projection.tsdescribe the shape correctly, so they are untouched — butheadingTreePaths's "in document order" claim is not strictly true: a heading whose text is an integer-like string (# 12) becomes an integer-index key and sorts ahead of the others (# Beta / # 12 / # Alpha / # 2enumerates as[["2"],["12"],["Beta"],["Alpha"]]). That is an engine/contract question, not a README fix, so it is filed separately rather than silently patched here.docs/is gitignored and built separately);pages/how_to.mdis the source that feeds it.site/index.htmlwas checked for the same drift and has none — it never shows the map's JS shape.🤖 Generated with Claude Code
https://claude.ai/code/session_011UMMqb4R5YU17gjVPrhva8