Commit Graph
533 Commits
Author SHA1 Message Date
Faabyy a7833e094d #807: Browse for Themes brings a template's slide master and layouts
Design › Browse for Themes… with a .pptx or .potx now does what PowerPoint
does: the file's first slide master and its layouts replace the master the
current slide uses (a preserved master stays beside it), stretched to this
deck's slide size. Each slide on the old master moves to the new layout with
the same name, else the same kind, and keeps its content as Layout does. One
undo step. A .thmx still brings its theme only.

Reuse Slides' master copy (media, fresh master, layout and shape ids) moves
into reuse::import_master so both commands share it.

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 22db926
# Last command done (1 command done):
#    pick 8992623 #807: Browse for Themes brings a template's slide master and layouts
# No commands remaining.
# You are currently rebasing.
#
# Changes to be committed:
#	modified:   ROADMAP.md
#	modified:   crates/engine/src/cmd/design.rs
#	modified:   crates/engine/src/cmd/reuse.rs
#	modified:   docs/file-format-parity.md
#
2026-10-18 17:46:44 +00:00
Kushagra Kumar 0a0ad04f47 fix(design): ensure Apply to All clears layout overrides when slides and masters match 2026-10-18 23:11:24 +05:30
Kushagra Kumar 74bc27f27e fix(design): preserve master and layout backgrounds on reset and copy (#891) 2026-10-18 22:28:15 +05:30
NetterSilverandClaude Haiku 5.5 03993057a4 fix: decode &nbsp; to a non-breaking space so blank paragraphs survive trimming
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 18:01:49 +02:00
NetterSilverandClaude Haiku 5.5 e54bd2ccb7 Read a newline in pasted HTML text as a space
Found while testing crates/engine/src/cmd/richclip.rs:257-283 (decode_text)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 17:57:05 +02:00
ZetenypappandClaude Opus 5.5 8e9c198c7c Duplicate repeats the move of the last copy, as in PowerPoint (#966)
Duplicating a shape, moving the copy and duplicating that copy again places
the next copy the same distance further on. Anything else, an undone copy or
another slide gets the usual offset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:47:04 +02:00
Brandon Thomas dfe40a17bf Merge pull request #856 from marcoarnulfo/feat/autoformat-ordinals 2026-10-18 11:18:18 -04:00
Brandon Thomas 0b6705c12c Merge pull request #943 from Zetenypapp/fix/click-in-front-931
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-18 11:18:18 -04:00
Brandon Thomas ef6e8cdc2f Merge pull request #946 from Zetenypapp/fix/edit-points-undo
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-18 11:18:17 -04:00
Brandon Thomas 9430673350 Merge pull request #886 from Silvertree2010/fix/h2169-shape-setbounds-shape-resize-acc
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-18 11:18:16 -04:00
Brandon ThomasandClaude Opus 5.5 efc279d6f2 Clamp overflowing geometry to the limit and keep rotated resizes in range
An overflow to infinity (move x=1e308 dx=1e308) now lands on the limit
instead of resetting to 0, and a rotated shape re-centred after a capped
resize stays within POS_LIMIT (CodeRabbit review).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:18:16 -04:00
Brandon Thomas c1184d64fd Merge pull request #902 from Silvertree2010/fix/h2405-comment-delete-with-an-invalid-i 2026-10-18 11:17:29 -04:00
Brandon Thomas 8b01ed3e88 Merge pull request #901 from Silvertree2010/fix/h2367-flip-horizontal-flip-vertical-on
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-18 11:17:29 -04:00
Brandon Thomas 9e1430e296 Merge pull request #898 from Silvertree2010/fix/h2311-change-case-capitalize-each-word
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-18 11:17:28 -04:00
Brandon Thomas 389c2c2921 Merge pull request #885 from switch87/feat/784-transparent-png-export 2026-10-18 11:17:19 -04:00
Brandon Thomas 4fcf593bac Merge pull request #948 from Zetenypapp/fix/duplicate-shape-ids
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-18 11:17:06 -04:00
Brandon Thomas 26371b0629 Merge pull request #947 from Zetenypapp/fix/huge-effect-sizes
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-18 11:17:06 -04:00
Brandon Thomas dfa91441e6 Merge pull request #802 from Faabyy/import-warnings-203
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-18 11:17:05 -04:00
Brandon Thomas 9eadf35c97 Merge pull request #893 from Silvertree2010/fix/h2209-reuse-slides-slide-reuse-leaves 2026-10-18 11:16:19 -04:00
Brandon Thomas f5a895ef75 Merge pull request #827 from Silvertree2010/fix/h1748-slide-fromoutline-insert-slides 2026-10-18 11:16:18 -04:00
Brandon Thomas eb417f0470 Merge pull request #795 from Silvertree2010/fix/h814-html-paste-drops-text-from-a-bar 2026-10-18 11:16:17 -04:00
Alexey 46dec4a660 fix(wasm): avoid std services that panic on wasm32-unknown-unknown at startup
recovery::instance_id() mixed std::process::id() into the instance hash —
on wasm32-unknown-unknown that panics (``no pids on this platform``, and
SystemTime is missing too), so the web app died before its first frame.
On wasm the browser clock (js_sys::Date::now(), already an engine dep for
comment timestamps) stands in.
2026-10-18 15:27:59 +02:00
NetterSilverandClaude Haiku 5.5 45eeb7c819 Add slides from an outline to the section of the slide they follow
Found while testing crates/engine/src/cmd/slide.rs:~393 (from_outline), crates/format/src/lib.rs:225 (add_outline_slides)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 12:18:49 +00:00
NetterSilverandClaude Haiku 5.5 3e729bbf08 Limit shape.setBounds, shape.resize and shape.move size and position
Found while testing crates/engine/src/cmd/shape.rs:215 (set_bounds; shape.resize at :~183 and shape.move at :~171 have the same problem)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 10:19:53 +00:00
NetterSilverandClaude Haiku 5.5 3f973b0d87 Mirror the rotation when flipping a rotated shape
Found while testing crates/engine/src/cmd/shape.rs:400-412 (flip; used by arrange.flipHorizontal / arrange.flipVertical)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 12:17:00 +02:00
NetterSilverandClaude Haiku 5.5 e5a3c9ca65 Change case across formatting run boundaries
Found while testing crates/engine/src/cmd/format.rs:693-715 (also the whole-shape path at :734-741)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 12:13:47 +02:00
ZetenypappandClaude Opus 5.5 8ee5094c60 Open: also cap effect sizes in inherited text styles and theme effects
Review follow-up. A huge glow or shadow could still arrive through what text and shapes inherit:
the deck's default text style, a master's title, body and other styles, a text box's or table
cell's own list style, and the theme's effect styles that shape styles point at. sane_numbers caps
those too; the test plants 10^18 pt glows in each and checks they come back capped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:41:36 +02:00
Faabyy 368e07493c PPTX: a slide that can't be read is reported, not dropped in silence (#203)
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
#
2026-10-18 09:18:46 +00:00
ZetenypappandClaude Opus 5.5 051d3b4fd3 Canvas: shapes in front of grouped text and of the edited box's edge take the click too
Review follow-up. The in-front check now also looks among the members of the group that holds
the edited text, and the edited box's frame (which drags it) yields to a shape in front of the
text at that spot; the box's own handles stay on top, as in PowerPoint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:56:38 +02:00
ZetenypappandClaude Opus 5.5 daae74b57e Open: cap absurd effect sizes from a file at what Format Shape allows
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>
2026-10-18 10:07:58 +02:00
ZetenypappandClaude Opus 5.5 5e8c1bcc51 Open: give shapes that repeat an id in a .deckcraft file fresh ones
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>
2026-10-18 10:04:22 +02:00
ZetenypappandClaude Opus 5.5 f4afe6d2df Edit Points: turning a shape into a freeform is one undo step
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>
2026-10-18 10:01:46 +02:00
ZetenypappandClaude Opus 5.5 a773fcfce9 Canvas: a shape in front of edited text takes the click (#931)
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>
2026-10-18 09:59:58 +02:00
Brandon ThomasandClaude Opus 5.5 19724866a6 Tests: fix two flakes (recovery lock held by a forked mkfifo; notes check not in yet)
recovery::another_running_instance_keeps_its_entries unlocks the other
instance's lock instead of only dropping it: a mkfifo child spawned by a
parallel test shares the open file until it execs, keeping the flock held
(seen on the FreeBSD VM).

spelling_tests::notes_menu_language_dialog_and_repeated_words waits for
the background notes check before right-clicking (seen on ubuntu CI).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:29:08 -04:00
NetterSilverandClaude Haiku 5.5 83f21e7cb9 Fix add overflow panic in table.columnWidth for a huge column index (#922)
Found while testing crates/engine/src/cmd/table.rs:540 (column_width)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-17 18:36:12 -06:00
NetterSilverandClaude Haiku 5.5 bdcbee8d0b Make edit.cut a no-op when only a text caret is set (#920)
Found while testing crates/engine/src/cmd/edit.rs:cut (about line 337) and delete (about line 523)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-17 18:35:36 -06:00
Hamza afd6d3a3eb Header & Footer: the automatic date takes a format
`HeaderFooter::date_format` is documented as the `datetime1`…`datetime13`
format for automatic dates, and nothing read it: grep found one hit, the field's
own declaration. The Date placeholder was hardcoded to `datetime1`, so the
footer date was always the short date, and a `dateFormat` parameter was accepted
and silently dropped — the command returned Ok, so a caller could not tell.

Everything else was already there: `datetime::field_text` renders all thirteen
types and Insert ▸ Date & Time already offers them. Missing was the wiring from
a choice to the placeholder.

`design.headerFooter` now takes `dateFormat`, refuses anything outside the
thirteen rather than ignoring it, stores it, creates the placeholder with that
field type, and updates an existing one when the format changes — as it already
did for a changed `dateText`. A fixed date still wins as plain text, and going
back to automatic restores the remembered format.

`datetime::DATE_KINDS` is the canonical list; `dialogs.rs` uses it rather than
its own copy of the same thirteen strings, and the Header & Footer dialog gains
a Format dropdown listing each type by what it would show now, enabled while the
date is automatic.

Not here: reading a deck does not populate `date_format`, so the dialog shows
datetime1 preselected for a deck whose dates are something else until the user
picks. That is a pptx read-side change and wants its own PR.
2026-10-17 17:17:37 +05:00
NetterSilverandClaude Haiku 5.5 a55b6cfa6f Clamp text.selectParagraph paragraph index to avoid overflow
Found while testing crates/engine/src/cmd/text.rs:1151 (select_para)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 05:46:04 +02:00
NetterSilverandClaude Haiku 5.5 70244c899d Reject invalid comment.delete index instead of clearing the slide
Found while testing crates/engine/src/cmd/review.rs:140-155 (delete)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 05:19:50 +02:00
Kushagra Kumar 432016fc96 Propagate Format Background Apply to All to slide masters (#891) 2026-10-17 00:06:26 +05:30
NetterSilverandClaude Haiku 5.5 d3fb412167 Remap slide links to the copies when reusing slides
Found while testing crates/engine/src/cmd/reuse.rs:~150 (reuse; slides get fresh ids but Action::Slide targets are never remapped)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 18:33:41 +00:00
Nikita RakitinandCursor beb883d036 Files: save and open outlines as RTF
Adds PowerPoint's Outline/RTF save type: slide titles at outline level 0
(bold, larger), body paragraphs indented at their outline level, bold,
italic and underline kept, non-ASCII as \u escapes. RTF outlines (ours,
PowerPoint's or a word processor's, by outline level or indent) open as
a presentation or drop in as slides.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-16 20:34:44 +03:00
Gert Pellin 392734a135 Export: transparent background docs and clearer refusal (#784)
The error for a non-PNG export says the option is for PNG export. ROADMAP,
file-format, UI parity and control protocol docs mention the option.
2026-10-16 16:42:42 +02:00
Gert Pellin 39e7fb1d4f Export: PNG with a transparent background (#784)
The renderer lays every slide background over white (as PowerPoint does),
so a PNG export was always opaque. A new transparentBackground option leaves
the slide background out (both the white underlay and the background fill),
so only what is on the slide is drawn over transparency. Shapes filled with
the background (useBgFill) still show it.

- render: RenderOpts::transparent_background
- engine: file.export {transparentBackground} (PNG only; other formats
  refuse it and write nothing), file.render {transparentBackground}
- UI: Transparent background checkbox in the Export dialog (PNG) and in
  File > Export > Change File Type > PNG; the web download honours it
- CLI: render --transparent
2026-10-16 16:30:52 +02:00
midasmatterhorn 013941e8e8 engine: a hostile text selection can't drive paragraph commands past the body
Paragraph commands (align, case, insert, paste, selectParagraph) iterated
for pi in a.0..=b.0 with both ends taken verbatim from text.select, so a
control-channel selection with caret u64::MAX spun the loop over 2^64
entries on the UI thread, and text.selectParagraph's at.0 + 1 overflow-
panicked in debug builds. Clamp every range at the body's last paragraph
and use saturating_add for the single-index arithmetic.

Regression test: paragraph_commands_clamp_a_hostile_text_selection —
fails on main with 'attempt to add with overflow' at cmd/text.rs:1151,
passes with the clamp.
2026-10-16 15:12:10 +03:00
skylar taylor-barrick 1dc69720db Merge pull request #866 from Silvertree2010/fix/h1968-table-insertrowbelow-insertcolum
Clamp huge index in table.insertRowBelow/insertColumnRight
2026-10-15 23:13:10 -06:00
skylar taylor-barrick ad6be08603 Merge pull request #798 from Silvertree2010/fix/h1435-paste-from-html-text-inside-b-st
Don't paste HTML text as bold when <b> sets font-weight:normal
2026-10-15 22:43:42 -06:00
NetterSilverandClaude Haiku 5.5 1bb408462c Clamp huge index in table.insertRowBelow/insertColumnRight
Found while testing crates/engine/src/cmd/table.rs:291

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 04:09:45 +00:00
skylar taylor-barrick be2f10d8cb Merge pull request #822 from Silvertree2010/fix/h1632-slide-duplicate-appends-the-copy
Keep slide.duplicate copies next to their source in the section
2026-10-15 18:29:50 -06:00
Marco Arnulfo 367c3488c5 Text: AutoFormat superscripts ordinals (1st, 22nd) as you type 2026-10-16 02:06:42 +02:00