fix(pptx): carry verbatim custGeom OOXML in deck JSON (cross-process serialize)#69
Merged
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.
Path B from the eon-deck custGeom investigation — the architecturally-correct fix for the cross-process failure mode (parse client-side → store deck JSON → serialize server-side).
Root cause (confirmed in code)
High-fidelity replay of imported elements depends on two module-global registries —
sourceBufferCache(pptxToDeck.ts:366) andelementSourceRegistry(line 394) — populated only byparsePptxand never serialized into the deck JSON. Per-element verbatim replay gates ongetElementSource(el.id)(deckToPptx.ts). So when serialize runs in a different process from the import, the registry is empty → every element is re-synthesised from its deck fields.Synthesis can't represent OOXML even-odd / winding (custGeom has no winding flag), so complex vectors blank. I verified the bicycle's synthesized custGeom is structurally perfect (6 closed subpaths, coords fill the box, no NaN) — which is exactly why the fix isn't "patch the synth" but "don't synth at all when we have the source."
Fix
The importer stamps the verbatim
<p:sp>of self-contained custGeom shapes onto the element aspristineOoxml = { xml, snapshot }, which rides in the deck JSON. On serialize, an unedited such shape (snapshot still matches) is replayed verbatim — exact source winding/geometry — instead of re-synthesised;cNvPr/@idis rewritten to avoid spTree collisions. Edited shapes fall back to synthesis.Same persist-in-JSON pattern already used for embedded fonts (
deck.fonts), scoped to vector shapes so JSON bloat is negligible (a few KB/deck — the collaborator measured ~13 KB across this 25-slide deck).Self-contained only: shapes whose source XML references
r:embed/r:id/r:link(images) ora:schemeClr(theme colours) are not stamped — the fragment would be invalid without the source archive/theme. Those still synth.Coexists cleanly with same-process replay: in-process, the shape is caught earlier by
isPristineImportedElement(registry hit) and replayed through the source archive;pristineOoxmlis the cross-process fallback only.Tests (+3, 61 pass)
pristineOoxml(withcustGeom+ snapshot) on a round-tripped self-contained custGeom shape.<p:sp>(source fill + marker present) and rewrites the collidingcNvPr id.tsc -bclean,build:libsucceeds. Branch is off post-#68main.Scope note
This is the durable class-killer for cross-process custGeom (and the pattern extends to radial/other preserved elements later). The
fill="darken"+ path→EMU synth fixes from #66 are already merged; this is complementary — it makes unedited vectors byte-faithful regardless of process.