Commit Graph
548 Commits
Author SHA1 Message Date
xc4pr 7858d589cd Design Ideas: switching ideas removes the Full-bleed title band (#1201) 2026-10-23 00:45:54 +02:00
NetterSilverandClaude Haiku 5.5 0ce545fcb8 Reject invalid row/col index in table row and column commands
Found while testing crates/engine/src/cmd/table.rs:234-238 (at), via crates/engine/src/cmd/mod.rs:318 (usize_param)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 18:46:51 +02:00
Samir Hanna Verza 07c8e2d77f M3: apply fill and outline edits to group members (#1079) 2026-10-22 13:20:11 -03:00
skylar taylor-barrick a2435383b1 Merge pull request #996 from Silvertree2010/fix/h2800-deleting-a-shape-that-is-an-anim
Clear animation triggers that point at deleted shapes
2026-10-22 07:50:16 -06:00
Dominik StrebelandClaude Opus 5.5 aa6f45ba2c Text: table text takes the master's other-text style
PowerPoint for Mac lays out a table's text in the master's other-text
style (p:otherStyle), while shapes and text boxes take the presentation's
default text style (p:defaultTextStyle). A synthetic deck with an
otherStyle of 14 pt and a defaultTextStyle of 26 pt, exported as PDF,
draws a table cell at 14 pt and a shape's and a text box's text at 26 pt.
DeckCraft laid cells out through a stand-in shape that wasn't a table, so
they took the default text style: a deck whose two styles differ (18 and
20 pt) drew its table text 2 pt too large and wrapped its cells.

master_list_style sends text in a non-placeholder table to otherStyle,
and Shape::table_cell builds the stand-in every cell layout uses (drawing,
row heights, text placement, the caret and selection in a cell) as a
table. The table shape itself resolves the same way, so the formatting
state of a selected table reports the size its cells draw at.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 08:49:42 +02:00
fchinuandClaude Sonnet 5.5 f71ce3fa9d Format Painter: paint paragraph formatting per covered paragraph
Paragraph properties now go only onto paragraphs the selection covers
whole, so partly covered end paragraphs and the paragraph after a
triple-click keep their bullets. Double and triple clicks apply the
painter only when they changed the text selection.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 13:46:05 +02:00
FaabyyandClaude fdfdb9e058 Reuse Slides: choose which slides of the other file to insert (#1103)
Reuse Slides… used to insert every slide of the picked presentation. It now opens a list
of that presentation's slides (number and title, all ticked), with Select All / Select None
and a Keep source formatting option, and inserts only the ticked ones after the current
slide. New query slide.reuseList {path | data} gives the list; slide.reuse already took
`slides`.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 08:04:19 +00:00
fchinuandClaude Sonnet 5.5 6f83ed464d Format Painter: apply on text selection, keep bullets on partial lines
The painter only applied when a shape was clicked. It now also applies
when a text range is selected by drag, double-click or triple-click.
Paragraph formatting (bullets, alignment) is copied only onto
paragraphs the selection covers whole.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 19:46:15 +02:00
NetterSilverandClaude Haiku 5.5 65564cfc1b Reject invalid slide index params instead of using the selection
Found while testing crates/engine/src/cmd/slide.rs:234 (delete); same pattern in index_of :182, move_slide :269, duplicate :193 and section_add :534

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 16:29:18 +02:00
NetterSilverandClaude Haiku 5.5 5beca8c1b6 Play animated GIFs inside groups
Fixes #1020

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 05:21:55 +00:00
NetterSilverandClaude Haiku 5.5 b75ea712e9 Count line breaks as one char in Find/Replace
Found while testing crates/engine/src/cmd/find.rs:107-121 (para_chars / para_matches; splice at :124)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:53:53 +02:00
NetterSilverandClaude Haiku 5.5 e34169ff75 Clear animation triggers that point at deleted shapes
Found while testing crates/engine/src/cmd/edit.rs:573-585 (delete)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 20:16:01 +02:00
ZetenypappandClaude Opus 5.5 86e7879f5e Duplicate: Undo and Redo forget the last Duplicate's move
A shape added after an Undo can get an undone copy's id; duplicating it then
used the move measured from the old original.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 19:52:41 +02:00
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 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 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
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
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 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
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