feat(pptx): applyEdits — lossless surgical-edit API#95
Merged
Conversation
Add applyEdits(source, plan, options?): a patch on the original .pptx bytes rather than a full re-serialize. Everything not named by an edit comes out byte-identical to the source (masters, layouts, theme, fonts, tags, notes, embeddings, untouched elements); the result opens in PowerPoint with no repair. - New elementLocationRegistry in the parser (getElementLocation) maps every element id -> its verbatim source XML block, with no placeholder filtering. - Ops: setText/clearText, setChartData (in-place chart fill keeping type/colour + a regenerated, consistent embedded xlsx so Edit-Data works), setTableData, setImage, removeElement, addChart, addDiagram, per-slide background, title. - Slide subset/reorder/repeat from the template; repeats deep-clone from a pristine view so edits never bleed across copies. - Removed slides + their exclusive parts reclaimed by a reachability sweep, then reconcileDanglingRels + content-type pruning. - Unresolved ids / unsupported layout-instantiation surface via onWarning. Tests on a synthetic 4-slide template incl. the acceptance test (untouched slide byte-identical, chart workbook updated, zero dangling rels).
…on-plan # Conflicts: # packages/slidewise/src/index.ts
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
Implements
applyEdits(source, plan, options?)— a lossless surgical-edit API that patches the original.pptxbytes instead of re-serializing a full deck. Everything not named by an edit comes out byte-identical to the source (masters, layouts, theme, embedded fonts,ppt/tags/*, notes, embeddings, and any untouched element), and the result opens in PowerPoint with no repair.This removes the lossy round-trip that produced the
custGeom/ SVG-fallback / dangling-rel fidelity bugs and lets hosts drop their defensive cleanup.serializeDeckstays for the live editor and from-scratch decks;applyEditsis the lossless path for template-derived output.API
Elements are addressed by the same stable ids
parsePptxreturns; slides by 1-based template index. CallapplyEditsin the same process as theparsePptxthat produced the plan.Ops supported
setText/clearText(preserve the template box + first-run styling, or rebuild from supplied runs),setChartData(in-place native-chart fill keeping type/colours and regenerating a consistent embedded.xlsxso Edit-Data still works),setTableData,setImage,removeElement,addChart,addDiagram, plus per-slidebackgroundand decktitle.How it works
elementLocationRegistryin the parser (getElementLocation) maps every element id → its verbatim source XML block, with no placeholder filtering (the existingelementSourceRegistryskips no-xfrmplaceholders, which would breaksetTexton titles).<p:sldIdLst>order. A repeated source slide is deep-cloned (slide XML + rels + editable deps) from a pristine view, so edits to copies never bleed.reconcileDanglingRels+ content-type pruning run as backstops.onWarninginstead of throwing.Scope note:
source: { layoutId }(layout-instantiation from scratch) is intentionally not in the lossless patch path — that'sserializeDeck's job.applyEditsemits alayout-unresolvedwarning and continues rather than shipping a wrong slide.Tests
New
apply-edits.test.ts(11 tests) on a synthetic 4-slide template — no branded fixture needed — including the spec's acceptance test: edits text on 3 slides, fills one chart viasetChartData, removes one sample chart, leaves slide 4 untouched, then asserts slide 4 + its media are byte-identical, the chart's embedded workbook reflects the new data, the package keeps its root rels / content types, and there are zero dangling rels.Two real bugs were caught and fixed while writing tests: an
rPrcapture regex that stopped at a self-closing child element (corrupting run styling), and a GC step that deleted the mandatory_rels/.rels(invalid package, masked because tests only checked surviving rels) — now covered by an explicit assertion.Verification
pnpm typecheck✅pnpm test✅ (169 passed, 9 skipped — the skips are branded-fixture-gated)pnpm --filter @textcortex/slidewise build:lib✅Minor changeset included.