feat(api): DocumentSession.pageIndex() — resolve anchors to pages#231
Merged
Conversation
pageIndex() resolves every declared anchor(...) to its final page in a single,
backend-neutral pass over the laid-out document — pageNumberOf("intro") for a
"see page N" cross-reference, forAnchor(...) for the full PageReference. New
public PageReference(anchor, page) and PageIndex (forAnchor / pageOf /
pageNumberOf / all / totalPages) in document.snapshot; PageIndexExtractor reads
the AnchorMarkerPayload marker fragments every anchored node already emits, so
the result is computed from the layout graph (not from rendered bytes) and a
duplicate anchor resolves to the same destination linkTo(anchor) jumps to.
Cached per layout revision alongside layoutSnapshot(); SessionChromeApi and the
snapshot format are untouched (no PlacedNode field, no formatVersion bump).
Verified: ./mvnw test -pl . — 0 baselines changed. PageIndexTest covers
multi-page resolution, duplicate last-wins, a split section resolving to its
start page, zero-anchor and null-argument leniency, and revision caching;
PageIndexAnchorAgreementTest renders to PDF and asserts the go-to destination
page equals pageOf(anchor). A runnable PageReferenceExample (two-pass
cross-reference) ships with a committed preview.
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.
Why
Anchors and internal links shipped in v1.9, but there was no way to read back an anchor's resolved page — so a document couldn't print a "see page N" cross-reference, and a clickable table of contents had no source for its page numbers without a two-pass render-and-reparse hack.
What changed
DocumentSession.pageIndex()→PageIndex(forAnchor/pageOf0-based /pageNumberOf1-based /all/totalPages) overPageReference(anchor, page)— new public types indocument.snapshot. Resolves every declaredanchor(...)to its final page in one pass.PageIndexExtractorreads theAnchorMarkerPayloadmarker fragments every anchored node already emits at its top-left — the same fragments the PDF backend turns into go-to destinations. SopageIndex()is backend-neutral and a duplicate anchor resolves to the same pagelinkTo(anchor)jumps to (last registration wins).layoutSnapshot()(new package-private cache slot).SessionChromeApiand the snapshot format are untouched — noPlacedNodefield, noformatVersionbump, no baseline regen (the marker-fragment approach sidesteps all of it).PageReferencecarries a singlepage(nostart/end).Lane: canonical public API (read side) + shared-engine (reads existing fragments, no mutation). Purely additive → japicmp-safe.
Verification
./mvnw test -pl .— 0 visual baselines changed.PageIndexTest: multi-page resolution (intro→1, body→2), duplicate→last-wins, an anchored section split across pages resolving to its start page, zero-anchor and null-argument leniency (no NPE), and revision caching (recompute is correct after a mutation, not just a new instance).PageIndexAnchorAgreementTest: renders to PDF and asserts thelinkTo(anchor)go-to destination page equalspageOf(anchor)— pins the backend-neutral guarantee against future divergence.PageReferenceExample(two-pass "see page N" cross-reference) with a committed preview and an examples README row.@since 1.9.0on all new public API. This is the read-side foundation for the upcoming native table-of-contents.