Skip to content

feat(api): container bookmark() — sections and containers as PDF outline targets#242

Merged
DemchaAV merged 3 commits into
developfrom
feat/container-bookmark
Jun 26, 2026
Merged

feat(api): container bookmark() — sections and containers as PDF outline targets#242
DemchaAV merged 3 commits into
developfrom
feat/container-bookmark

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Why

A PDF bookmark (outline entry) could be set only on the seven leaf builders. A structural unit — a Section, a Container, a page flow — could not be a navigable outline target, so a multi-chapter document had no bookmark panel unless every chapter pinned a leaf bookmark by hand.

viewerPreferences() (page mode / layout / window flags, where USE_OUTLINES auto-opens this panel) follows as a separate PR.

What changed

  • bookmark(DocumentBookmarkOptions) on AbstractFlowBuilder — makes any container flow (Section / Container / page flow) a PDF outline entry pointing at its start page.
  • Emitted as a new non-visual BookmarkMarkerPayload fragment, gated to the container's start page (mirroring the existing withAnchorMarker), that rides the backend's generic bookmark-registration branch — a no-op PdfBookmarkMarkerRenderHandler covers fragment dispatch, and registration reuses the existing registerBookmarkPdfBookmarkOutlineWriter path (no deferred resolution, unlike an anchor).
  • Because the bookmark has its own marker fragment rather than riding the background decoration, it works on an unstyled container too (a decoration-payload approach would have dropped it).

Lane: canonical DSL (AbstractFlowBuilder, SectionNode, ContainerNode) + a shared-engine marker emission. Purely additive → japicmp-safe (the new SectionNode 13th / ContainerNode 11th components ship behind re-declared back-compat constructors).

Verification

  • ./mvnw test -pl .green, 0 changed visual baselines → a container without a bookmark emits the same fragments as before. ./mvnw -P japicmp verify — binary-compatible.
  • ContainerBookmarkTest (5): two bookmarked sections become outline entries at their pages; an unstyled section still emits its bookmark; a multi-page page flow (a ContainerNode) emits its entry exactly once at the start page (the split-gating edge); a section without a bookmark adds no entry; the back-compat SectionNode constructor defaults to no bookmark.
  • A cold review confirmed the byte-identity, the marker/registration path (the no-op handler is required for dispatch), the start-page gating, and the back-compat ctors; it drove the multi-page page-flow test.
  • Runnable ContainerBookmarkExample + committed preview: a report whose four sections are each an outline entry (verified via the PDF's outline).

DemchaAV and others added 3 commits June 26, 2026 09:29
…ine targets

A PDF bookmark (outline entry) could be set only on the seven leaf builders; a
structural unit — a Section, a Container, a page flow — could not be a navigable
outline target, so a multi-chapter document had no bookmark panel unless every
chapter pinned a leaf bookmark by hand.

bookmark(DocumentBookmarkOptions) on AbstractFlowBuilder makes any container flow
an outline entry pointing at its start page. It is emitted as a new non-visual
BookmarkMarkerPayload fragment — gated to the container's start page, like the
existing anchor marker — that rides the backend's generic bookmark-registration
branch (a no-op render handler covers fragment dispatch). Because the bookmark
has its own marker fragment rather than riding the background decoration, it
works on an unstyled container too. A container without a bookmark emits the same
fragments as before, so existing documents are byte-for-byte unchanged.

Tests: ContainerBookmarkTest asserts two bookmarked sections become outline
entries at their pages, an unstyled section still emits its bookmark, a multi-page
page flow emits its entry exactly once at the start page, a section without a
bookmark adds no entry, and the back-compat SectionNode constructor defaults to no
bookmark. Example: ContainerBookmarkExample (a report whose sections are each an
outline entry). Full suite green, no visual baselines changed.
Threading the container bookmark through ModuleBuilder switched its buildNode to
the full SectionNode constructor, which also started honouring bleed() — a module
previously ignored bleed. Pass DocumentBleed.none() explicitly so a module's bleed
behaviour stays as it was; only the bookmark is threaded through.
@DemchaAV DemchaAV merged commit 533b218 into develop Jun 26, 2026
11 checks passed
@DemchaAV DemchaAV deleted the feat/container-bookmark branch June 26, 2026 09:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant