Commit Graph
533 Commits
Author SHA1 Message Date
NetterSilverandClaude Haiku 5.5 744c01f66f Match style as a whole attribute name in HTML paste
Found while testing crates/engine/src/cmd/richclip.rs:230-242 (attr, used by tag_style)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 14:35:42 +00:00
NetterSilverandClaude Haiku 5.5 35f240e453 Return BadParams for overflowing start in review.spellingChange
Found while testing crates/engine/src/cmd/review.rs:424 (spelling_change)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 13:53:26 +00:00
KataccandClaude Opus 5.5 66e369de26 Doc comments for the language functions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 16:31:55 +03:00
KataccandClaude Opus 5.5 291725c78e format.languageAll: also mark each text body's own list style
A layout placeholder's a:lstStyle can carry lang/noProof, and
ed::format_all only touched runs and end marks, so such a placeholder
kept its old language. Existing list style levels of shape, table cell
and notes bodies now get the edit too; bodies without one get none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 16:31:55 +03:00
KataccandClaude Opus 5.5 2d3997d2e3 Review: proofing language for the whole presentation
Review › Language gets "Apply to: Selected text / Whole presentation".
The new format.languageAll command sets lang/noProof on every run in
the deck (slides, groups, table cells, notes, masters, layouts) and on
the master and default text styles, so new text inherits it. It needs
no selection and is one undo step; format.language is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 16:31:35 +03:00
dotCooCoo e89c824c6d Text: a Columns dialog sets the number of columns and the spacing between them
Home > Columns offered 1, 2 or 3 columns, always 18 pt apart, and Format
Shape > Text Box had the same three buttons. The spacing could not be
seen or changed, and picking a number reset it.

Home > Columns > More Columns... and a Columns... button in Format Shape
> Text Box now open a Columns dialog with Number (1 to 16) and Spacing in
inches, filled in from the text box. OK applies both in one undo step.
A Spacing left as shown keeps the text box's exact value.

format.columns with no fields opens the dialog. A key left out keeps the
text box's own value instead of resetting it to 1 column or 0 pt, and a
count that is not a whole number from 1 to 16, or a spacing that is not
a number, is an error. Before, an out-of-range count was clamped, a
count that was not a whole number meant 1 column, and a spacing that
was not a number meant 0 pt.
2026-10-24 05:57:36 -07:00
NetterSilverandClaude Haiku 5.5 fb778030c9 Reject invalid shape ids in ids instead of using the selection
Found while testing crates/engine/src/cmd/mod.rs:ids_param / targets (~line 335-350)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 10:13:35 +00:00
dotCooCoo e8910cb253 Paste: a table, bullet or slide from another deck keeps its own pictures and sounds
Copy listed the media of pictures, media clips, 3-D models and shape
fills only, and Paste rewrote the ids of pictures, media clips, opaque
previews and shape fills only. Picture fills in table cells and table
backgrounds, picture-filled text runs and picture bullets were left off
the clipboard. In another deck they pointed at a missing picture, or at
that deck's own picture when it used the same media id. A copied slide
lost its transition and animation sounds in the same way.

Paste Special > Picture gave clashing media fresh ids but drew the
shapes with the old ids, so a clashing id drew the open deck's picture.
Review > Compare > Accept Revision of a compared deck's slide copied the
same partial set, and missed the slide background as well.

Copy, Paste, Paste Special > Picture and Accept Revision now find and
rewrite media ids with the media_refs walkers that slide.reuse uses.
2026-10-24 02:48:19 -07:00
aiongg 528af4e503 Integration: a rejected positional revision is not turned into a deletion when a slide is inserted before it 2026-10-24 09:40:33 +00:00
aiongg a453292729 Merge main into the integration batch 2026-10-24 09:20:03 +00:00
aiongg e679fa500a Integration: right-clicking a control handle in Edit Points keeps the picked point and its menu 2026-10-24 09:17:30 +00:00
aiongg 027075d352 Integration: a rejected positional revision stays rejected after a slide is inserted or deleted in the open deck 2026-10-24 09:16:08 +00:00
aiongg 2bbfe46d3e Integration: slides with two visible pictures get no layout ideas 2026-10-24 09:14:11 +00:00
aiongg 9dcb7bab03 Integration: the automatic-date test reads the clock before and after the command so a tick of the second cannot fail it 2026-10-24 09:13:29 +00:00
Dylan M. Taylor c955407373 security(engine): check regular file and size bound on read, preserve permissions and symlinks on save (#1265)
* security(engine): check regular file and size bound on read, preserve permissions and symlinks on save

* style: format recovery.rs write_atomic
2026-10-24 04:45:48 -04:00
Dylan M. Taylor 6189fa8bf6 perf(engine): bound HTML entity semicolon scan window and formatting stack search (#1267) 2026-10-24 04:41:43 -04:00
SusieeTheFemboyandGLM-5.3 238b34be00 Media: a video with an unsupported codec says only its audio plays (#1237)
insert.video answered playable=true with no warning for a clip whose video
codec has no decoder (a VP8 + Vorbis WebM, say): its audio track plays, but
the slide shows an unexplained black box, which reads as "black with no
audio". The insert now warns that the video can't be played yet and only
the audio plays.

The missing audio itself is not reproducible: through the real insert +
play path the Vorbis track of a VP8 WebM decodes and sounds, on main and on
0.10.0 (the reporter's build). A regression test drives that whole path, on
a new synthesised clip-vp8.webm fixture.

Co-Authored-By: GLM-5.3 <noreply@z.ai>
2026-10-24 10:41:30 +02:00
dotCooCoo 9888d7c90e Tables: dragging across cells selects a range of cells
While the caret is in a table cell, a drag into another cell of the
table now selects the cells between them. The range takes in every
merged cell it touches, and the canvas shades the selected cells.
Moving back into the first cell returns to a text selection there.
Shift+arrow moves the cell the range was extended to, and the cell it
started from stays.

With a range selected, run and paragraph formatting apply to those
cells only. Delete clears their text and keeps the cells and the table,
and Copy and Cut take their text, with a tab between cells and a line
per row. Shading, Borders, Cell Margins and Align take in the merged
cells the range touches. A press in the table starts again in the cell
under the pointer.
2026-10-24 01:29:58 -07:00
Dylan M. TaylorandClaude Sonnet 5.5 d94790d97a refactor: replace redundant closures with method paths (SonarCloud S1612) (#1261)
Skipped where the receiver type is generic or not evident without a compiler (wrapping_neg, total_cmp, exists, to_vec, as_ref, split_first, Option::into_inner).

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 04:27:07 -04:00
dotCooCoo 05f2a84400 Text: text.insert reports the caret where AutoCorrect leaves it
text.insert returned the caret from before AutoCorrect ran. After a
typed space started a list, it reported (0, 2) for `* ` while the caret
was at (0, 0) in the emptied paragraph, and after `(c) ` it reported
(0, 4) for the two-character `© `. It now reports the caret from the
selection after AutoCorrect.
2026-10-24 00:44:36 -07:00
NetterSilverandClaude Haiku 5.5 ee248bb5cb Decode numeric tab entities in HTML paste
Found while testing crates/engine/src/cmd/richclip.rs:304 (numeric_char, used by decode_text)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 07:18:46 +00:00
aiongg 8957e193e9 Merge integration track r1-t02 (dialogs, view, text editing, panes, status bar, other)
ROADMAP.md, docs/gaps.md: union of both tracks' log rows.
2026-10-24 06:26:36 +00:00
aiongg abd8768b65 Merge PR #565: Files: save and open outlines as RTF
Conflicts:
crates/engine/src/cmd/file.rs: export spec keeps main's transparentBackground and adds rtf; probe_clips (main) and outline_text (PR) both kept
docs/file-format-parity.md: PR's outline row (RTF now read) with main's .md wording, main's PNG row
2026-10-24 06:18:03 +00:00
aiongg 5b5fd5eabe Merge PR #1109: Reuse Slides: choose which slides of the other file to insert
Conflicts: ROADMAP.md (union of both sides' rows)
2026-10-24 06:17:26 +00:00
aiongg 2693336155 Merge PR #809: Design: Browse for Themes brings a template's slide master and layouts (#807)
Conflicts: ROADMAP.md (union of both sides' rows)
2026-10-24 06:17:23 +00:00
aiongg f52c911959 Integration: #927 Header & Footer dialog sends dateFormat only when picked; set_date doc comment back above set_date
Without it, Apply rewrote every slide's existing date field to datetime1.
2026-10-24 06:17:19 +00:00
aiongg 0313e0128a Merge PR #850: Review: reject revisions after Compare, one or all
ROADMAP.md, docs/gaps.md: kept main's lines and the PR's single added line in each table.
2026-10-24 06:16:50 +00:00
aiongg 5880086522 Merge PR #927: Header & Footer: the automatic date takes a format 2026-10-24 06:16:45 +00:00
aiongg b7c505a389 Merge PR #1254: Reject invalid index in slide.hide and slide.layout
Conflicts: crates/engine/src/tests.rs (appended both sides' tests)
2026-10-24 06:16:45 +00:00
aiongg 987f49ac03 Merge PR #1252: Reject '+'-signed numeric character references in HTML paste 2026-10-24 06:16:43 +00:00
aiongg 92724e02bb Merge PR #1205: Design Ideas: no ideas for slides with diagrams, connectors or other graphics (#1200)
Conflicts: crates/engine/src/cmd/ideas.rs (test module: kept both sides' tests)
2026-10-24 06:16:39 +00:00
aiongg c480b74a3f Merge PR #833: Shapes: Edit Points — Straight/Curved Segment and Open/Close Path from the right-click menu
Conflicts: ROADMAP.md docs/gaps.md docs/ui-parity.md (union of both sides' rows)
2026-10-24 06:16:21 +00:00
aiongg 2fd32751cc Merge PR #1251: Fix arrange.distribute span to use the selection's full extent 2026-10-24 06:16:21 +00:00
aiongg 78afd2fc45 Merge PR #1245: Title: arrange.group: nest groups at most 32 deep 2026-10-24 06:16:18 +00:00
aiongg f2e2fcaba4 Merge PR #1015: Chart text can be coloured (chart.options textColor, format.color) and follows the theme by default
Conflicts: crates/engine/src/cmd/insert.rs (kept main's apply_bin_options / apply_subtotals_and_bars helpers and added the textColor assignment)
2026-10-24 06:15:53 +00:00
aiongg 6971d55345 Merge PR #799: Text boxes: a click on the frame selects the box whole (#787)
docs/ui-parity.md: kept main's status header lines; the PR's older header dropped, its new table row kept.
2026-10-24 06:15:50 +00:00
aiongg aed303e504 Integration: #956 chart.options dataLabels resets the series' own settings
Without it, turning Data Labels on did nothing for an imported chart whose series read showVal 0.
2026-10-24 06:15:41 +00:00
aiongg 7fd34fb359 Merge PR #813: engine: a hostile text selection can't drive paragraph commands past the body 2026-10-24 06:15:03 +00:00
aiongg 5827d3b4c1 Merge PR #904: Clamp text.selectParagraph paragraph index to avoid overflow 2026-10-24 06:15:03 +00:00
dotCooCoo e04ef2b4a8 Text: AutoFormat starts bulleted and numbered lists as you type
A paragraph that starts with *, -, --, >, <>, 1., 1), I., i., A., a.
or a) followed by a space or tab now becomes a bulleted or numbered
list in that style through format.bullets or format.numbering, and the
typed lead and space are removed. The keystroke is one undo step.
Backspace right after the change puts the typed text and the
paragraph's formatting back.

Tools ▸ AutoCorrect has "Automatic bulleted and numbered lists" to turn
it off, and text.autocorrect takes and reports it as lists.
2026-10-23 22:06:56 -07:00
5fadda5ecf chore: resolve SonarCloud maintainability issues (#1255)
* chore: resolve SonarCloud maintainability issues

* fix: address shellcheck SC2059 and fix generic cast ambiguity

* style: apply rustfmt formatting

* fix: restore compile and behaviour in Sonar refactors

- fonts: char::is_alphanumeric takes &self, so filter needs a closure
- h264: keep the mvd accumulator as i32 (prefix is usize)
- model: annotate the non-stacked range accumulators as f64
- engine: chart.options still clears the raw chart XML for upDownBars
  and quartiles; smartart goes back to the glob import (cmd! macro)
- web: keep the original viewport meta (behaviour change)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Assign positional parameters to locals in sha256 verification

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Dylan Taylor <dylan@craftmaker.dev>
2026-10-23 23:28:09 -04:00
NetterSilverandClaude Haiku 5.5 6d7b32351f Reject invalid index in slide.hide and slide.layout
Found while testing crates/engine/src/cmd/slide.rs:376 (hide); same pattern at slide.rs:445

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 02:16:19 +00:00
NetterSilverandClaude Haiku 5.5 fc914a059c Reject '+'-signed numeric character references in HTML paste
Found while testing crates/engine/src/cmd/richclip.rs:301-304 (numeric_char, used by decode_text)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 01:23:11 +00:00
NetterSilverandClaude Haiku 5.5 18e8bb0ded Fix arrange.distribute span to use the selection's full extent
Found while testing crates/engine/src/cmd/arrange.rs:325-327 (distribute)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 01:07:34 +00:00
Zach BerryandClaude Fable 5.1 0c510426af Chart text without a colour of its own takes PowerPoint's default grey
The theme's bare text colour made chart text black on a light theme,
where it used to be 595959. PowerPoint's default is `tx1` at lumMod 65000
and lumOff 35000: 595959 on a light theme, a light grey on a dark one, so
the dark-theme fix stays. The render test now checks the light-theme title
is dark but not black; the chart.options doc says what null gives.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-23 19:57:50 -05:00
Zach BerryandClaude Fable 5.1 1b03ae95de format.color on a selected chart colours the chart's text
Font Color with a chart selected answered and changed nothing: a chart
has no text runs to colour. It now sets the chart's text colour (title,
axes, legend and data labels), the same thing chart.options {textColor}
sets; a mixed selection still colours the other shapes' runs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-23 19:57:50 -05:00
Zach BerryandClaude Fable 5.1 a48a2d706a chart.options takes textColor so a chart's text can be coloured
On a dark theme a chart's title, axis labels, legend and data labels
render in a fixed grey and nothing could change them, though the model
already carries `text_color`. `chart.options {textColor}` now sets it
(#RRGGBB, accent1…accent6, tx1…, or null for the default) and refuses a
string that isn't a colour. docs/mcp.md mentions it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-23 19:57:50 -05:00
aiongg 9aef21e627 Media: a clip opened from a .pptx gets its length and size from its headers (#1241) (#1250) 2026-10-23 19:56:24 -04:00
NetterSilverandClaude Sonnet 5.5 9679c6e16f fix: Name registered table commands in errors and reject invalid cell params
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 01:13:55 +02:00
KataccandClaude Opus 5.5 8117d5b710 arrange.group: nest groups at most 32 deep
Grouping a group again and again had no limit, but a .deckcraft saved
with 39 or more nested groups could not be opened again (the JSON
reader's recursion limit), and past 64 levels shape walks such as
format.languageAll stop. arrange.group now refuses to nest past 32,
the depth the PPTX reader reads and the renderer draws, and leaves the
slide unchanged. The test builds the deepest allowed deck (a table at
the bottom) and checks it saves and reopens.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 01:02:21 +03:00