feat(render-pptx): chrome, navigation, multi-section, and deterministic output#414
Merged
Conversation
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
The fixed PPTX backend rendered every fragment payload but stopped at the document level: chrome (metadata, watermark, headers/footers) configured on a session was silently dropped, recorded links and bookmarks were never emitted, multi-section documents threw, and every render produced different bytes because POI stamps wall-clock times into the OPC properties and every zip entry.
What
PptxChromeRendererrenders the canonical chrome with the PDF backend's math: metadata lands in the OPC core properties plus the extended application property (OPC has no producer field); text watermarks measure with Helvetica-Bold, orbit the frame centre around the PDF's baseline-start rotation pivot, and carry opacity as colour alpha; image watermarks use nativealphaModFix; tiling matches the PDF grid (invisible off-slide tiles are skipped); headers/footers resolve{page}/{pages}/{date}with the full numbering-window rules and draw separators as connectors. Behind-content watermarks apply before fragment rendering, so document order reproduces the PDF's layering without z-order surgery. Protection, viewer preferences, and debug overlays have no PPTX counterpart and are skipped with a one-time warning.PptxNavigationWriterafterwards as transparent hotspots above all content: external targets as URL hyperlinks, internal targets as slide-jump hyperlinks resolved against the anchor map (forward references work; a dangling anchor warns and skips). Inline-graphic spans get baseline-aligned hotspot boxes, mirroring the PDF's span rectangles. The first bookmark on a page names its slide.renderSections/writeSectionsconcatenate sections into one deck: per-section chrome with section-local page numbering, cross-section navigation against the combined deck, first-declaring-section metadata, and fonts embedded once from the union. A deck carries one slide size, so differing page canvases are rejected. A raster-slide section still resolves incoming links and bookmarks; its own outgoing navigation is baked into the pixels.Builder.deterministic(boolean | Instant)pins the OPC created/modified properties and rewrites the finished archive with zone-independent zip entry times, making render-twice byte-identical.renderToImagesstays unsupported with a pointer to the PDF backend; capability matrix and CHANGELOG updated (the clip row now links the vector-clip follow-up pptx: replace the clip raster fallback with true vector clipping #413).Verification
render-pptx/target/visual-tests/pptx-parity/chrome-nav/(PDF + PPTX + per-page PNGs at matching scale).clean verifyacross core, render-pdf, render-docx, render-pptx, templates, testing, root, bundle, qa, coverage.