The PPTX import numbers shapes per slide, so two slides can hold different
videos under one shape id. find_clip searched the whole deck and took the
first match, so the show's media cues, the keep-across-slides filter and
the media.* requests all got the first slide's clip: from slide 3 on, video 2
played. find_clip now takes the slide the request comes from and searches it
first, then the rest of the deck.
Co-Authored-By: Claude <noreply@anthropic.com>
The importer skipped a slide whose part was missing or unreadable and only
logged it, so `info` showed one slide fewer with exit code 0 and a save wrote
the shorter deck over the original.
`deckcraft_pptx::import_checked` returns the parts it left out (`import` is
unchanged). The engine carries them as `Damage::slides` next to the damaged
media of a `.deckcraft` file: `file.open` and `file.openBytes` return
`lostSlides`, the app shows a message and opens a repaired copy (so Save asks
for a new name), and `deckcraft-cli` warns on stderr.
Co-Authored-By: Claude Code <noreply@anthropic.com>
# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# interactive rebase in progress; onto 1dc6972
# Last command done (1 command done):
# pick d2e995c PPTX: a slide that can't be read is reported, not dropped in silence (#203)
# No commands remaining.
# You are currently rebasing.
#
# Changes to be committed:
# modified: Cargo.lock
# modified: ROADMAP.md
# modified: apps/deckcraft-cli/Cargo.toml
# modified: apps/deckcraft-cli/src/main.rs
# new file: apps/deckcraft-cli/tests/damaged.rs
# modified: crates/engine/src/cmd/file.rs
# modified: crates/engine/src/tests.rs
# modified: crates/pptx/src/lib.rs
# modified: crates/pptx/src/read/mod.rs
# modified: crates/pptx/tests/malformed.rs
# modified: docs/file-format-parity.md
#
# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# interactive rebase in progress; onto 22db926
# Last command done (1 command done):
# pick 31b0d33 PPTX: a slide that can't be read is reported, not dropped in silence (#203)
# No commands remaining.
# You are currently rebasing.
#
# Changes to be committed:
# modified: Cargo.lock
# modified: ROADMAP.md
# modified: apps/deckcraft-cli/Cargo.toml
# modified: apps/deckcraft-cli/src/main.rs
# new file: apps/deckcraft-cli/tests/damaged.rs
# modified: crates/engine/src/cmd/file.rs
# modified: crates/engine/src/tests.rs
# modified: crates/pptx/src/lib.rs
# modified: crates/pptx/src/read/mod.rs
# modified: crates/pptx/tests/malformed.rs
# modified: docs/file-format-parity.md
#
A .pptx or .deckcraft could give a glow, soft edge, shadow or reflection any size. A glow of
~10^16 pt made vello panic while flattening, one of 10^18 pt made rendering ask for 34 GB and abort.
sane_numbers (run by repair on every opened file) now caps them like line widths and font sizes:
glow 150, soft edges 100, shadows 200, reflections 100 pt; shadow scale and skew are kept sane and
non-numbers become 0, on shapes and on text runs, table cells included.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
repair re-id'd repeated slide ids but not shape ids, so such a file opened as a deck that fails
validate, and edits by id found only the first of the shapes sharing one. Repeats on a slide,
layout or master (groups included) now get fresh ids from the deck's counter; the first keeps
its id, and decks without repeats aren't copied.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shape.editPoints was a noundo command, so the conversion from a preset to custom geometry was
never recorded and Ctrl+Z took back the step before it. It is undoable now (only an actual change
records a step), and Edit Points ends when Undo turns the shape back into a preset.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While a placeholder's text was being edited, place_caret took every click inside the text box
before the hit test, so a shape in front of it couldn't be selected. It now leaves the click to
the hit test when a shape above the one holding the text is under the pointer; a click on the
text where nothing is in front still moves the caret.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep later On Click effects and paragraph builds in separate interactive steps.
Add round-trip and headless show regressions.
Contribution on behalf of @MMexicann.
slides_to_outline only looked at sh.text, which regular text boxes and
placeholders carry. Tables store their text in cells inside
ShapeKind::Table, so convert to .txt or .md silently skipped every
table cell — with exit 0 and no warning.
The outline now walks into tables: each row becomes a tab-separated
line (multi-paragraph cell text is flattened with spaces). Verified
with the issue's python-pptx repro: the four cell texts appear after
the slide title and text box body.
Tests: a deck with a text box and a 2x2 table — the outline contains
all three text sources.
Preserve notes and handout master export, visible text and native parallel
compression while propagating shared font errors through each export path.
Keep the dependency check accurate for native and WASM feature resolution.
PR #708.
anchorCtr's centreing offset was computed for a block that starts at
the box's left edge and then added to lines that alignment had already
placed within the box. For a right-aligned line the two shifts
stacked: the line ended up starting at the box's centre and ran past
the right edge - on the tdf165341 fixture the sentence was cut off at
"...paragraph rig". The clamp at zero made it worse for content wider
than the box: all the overflow went to the right only.
The origin is now set so the drawn text block's own centre (min/max of
the laid-out line extents) lands on the box's centre: every alignment
stays inside the box when it fits, and overflow centres symmetrically
past both edges, as PowerPoint draws it. Empty lines carry no ink and
stay out of the block; vertical text and multi-column bodies are
unchanged (centring is unimplemented for them, as before).
Tests: right/left-aligned, trailing empty paragraph, mixed alignment,
symmetric overflow, and a no-anchorCtr control - the block's centre
equals the box's centre in every case.
Reported with a public LibreOffice test fixture (tdf165341.pptx);
verified by rendering the slide before (text cut at the right edge)
and after (whole sentence centred).
Conflicts resolved onto main's newer shape, and the PR's policy applied to
every alloc_id/add_media/new_slide call site main has grown since: commands
answer bad(cmd, NO_ID_SPACE) (slide.reuse, insert.zoom, SmartArt, photo
album, review.accept, handout/notes masters, master placeholders,
background/artistic/compress pictures, transition sound, ink to shape,
paste special, file.new templates); reid/bring_media/renumber/regenerate
and compare::adopt/accept are fallible; outline import keeps what fit.
Tests use expect() on the now-Option results.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reject unrelated, malformed, incomplete and oversized replies without replaying commands.
Reconnect before sending when unsolicited reply bytes are buffered.
Contribution on behalf of @MMexicann.
Union merges of the 2026-10-14 community PR wave stacked header lines and
left near-duplicate rows, bullets and paragraphs with per-PR counts. Each
progress doc now has one status line and one row per fact, with current
numbers: breadth 84% over 191 features (cargo xtask parity, after removing
duplicate Thesaurus/AutoCorrect/Artistic effects/Corrections checklist
rows), 320 engine commands, 41 dialogs, 1,641 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- review.thesaurus's params doc parses under describe's grammar; describe's edit.copy test
expects the landing branch's {text, html?} answer.
- The Language dialog test picks the landing branch's "Français (France)" entry; the Format
Background test allows the pane's title to appear twice.
- Progress docs rebuilt from the landing branch's versions with land-r6's rows applied on top,
so the union merge no longer drops the pen-pressure, ui.pointer and ui.key rows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fix-ups in the merge (review): uniform-width and highlighter strokes are drawn as one path (on
the slide and in the live preview) so see-through ink doesn't darken where segments overlap;
segment pairs are destructured instead of indexed; tests that build pointer events set the new
pressure field.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With only an image on the system clipboard egui-winit drops Ctrl+V, so #702's
picture copy of a textless shape undid main's #182 fix. Text keeps #702's HTML,
and empty plain text falls back to the marker.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>