Commit Graph
1944 Commits
Author SHA1 Message Date
Martin BallandClaude Opus 5.5 0ecdf2ff2d #3710: .doc floating shapes built once per spid; anchor copies charged to the work budget
Finding 49. drawing::anchors built a fresh object for every PlcSpa entry,
so one group of 1000 members named by 5000 entries built 5M children
(1.4 s, ~1 GB) with the per-group child cap resetting each time. Word
anchors each shape once, so a repeated spid is now skipped: every node of
the shape tree is built at most once, bounded by the shared OfficeArt
record budget. walk also cloned each floating object every time a story
holding its anchor was walked; each copy is now charged by size (a group
with all its members) to the document-wide MAX_WORK budget.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 23:47:26 +00:00
Martin BallandClaude Opus 5.5 878bac84ba #3709: .doc inline-picture alt text copies charged to a work budget
Finding 68. Pictures::get cloned the cached Inline (alt text up to 4096
UTF-16 units) for every '\x01' anchor, and the char budget allows ~64M
anchors, so one picture referenced repeatedly could copy hundreds of GB.
get now returns a reference; walk copies the alt text per anchor only
while the document-wide work budget lasts, then leaves it empty (the
picture itself is still placed).

The Prm work budget from #3692 becomes one shared MAX_WORK (64 MiB) for
repeated work beyond the text: Prm grpprls interpreted, hyperlink targets
(#3708, moved off the char budget so long links in small files are never
dropped) and alt text copied.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 23:47:26 +00:00
Martin BallandClaude Opus 5.5 36e43fa672 #3692: .doc piece Prm resolved once per formatting change, under a work budget
Finding 64. push_formatted re-ran char_props and apply_prm for every
character, so a single piece whose Prm names a 63 KB Prc over 100k
characters took 15 s. walk now keeps the last resolved CharProps and
reuses it while the CHPX slice, the piece's raw Prm and the paragraph
style are unchanged. Prm1 grpprl bytes interpreted are charged to a
document-wide MAX_PRM_WORK (64 MiB) budget, so files alternating pieces
per character can't multiply the work; past it the Prm is skipped.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 23:47:26 +00:00
Martin BallandClaude Opus 5.5 dc3a999081 #3708: .doc hyperlink target copied once per run, charged to the char budget
Finding 75. finish_field cloned the HYPERLINK target into every result
character's CharProps and ParaBuild::push then compared it per character,
so a long target over a long result was quadratic (250k x 250k: 2.6 s).
Equal-formatted result characters now extend the current run; each run
start copies the target once and charges its length to the document's
character budget, past which the rest of the result is kept unlinked.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 23:47:26 +00:00
Martin BallandClaude Opus 5.5 e73ce9c274 #3642: .doc reader checks the compound file's DIFAT before cfb builds the FAT
Finding 63. cfb 0.15 appends a whole sector of FAT entries for every FAT
sector the DIFAT lists and validates the FAT only afterwards, so a small
file whose DIFAT chain names one sector thousands of times made it
allocate ~128x the file size (2048 DIFAT sectors: 133 MB, 370 ms) before
failing. docbin now walks the header DIFAT and chain the way cfb does
(same trimming, one step per sector) and refuses a file listing more FAT
sectors than it has sectors, so the FAT is never larger than the file.
Both is_encrypted and read_with_password go through it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 23:47:26 +00:00
Dylan M. Taylor 6d3370635d Merge pull request #4356 from storytold/chore/deps-safe-refresh
chore(deps): safe dependency refresh
2026-10-25 19:27:38 -04:00
skylar b729cf0cb4 fix(proof): keep inflate error output out of messages 2026-10-25 16:57:21 -06:00
skylar 68407a34cd chore(deps): bump miniz_oxide to 0.9 2026-10-25 16:57:11 -06:00
skylar a1aa17fc14 fix(deps): keep miniz_oxide at 0.8 2026-10-25 16:53:12 -06:00
skylar 5ee71b4862 chore(deps): refresh safe dependency bumps
serde_json 1.0.154, proptest 1.12, base64 0.23, arboard 3.7, open 5.4.5,
winresource 0.1.34, pollster 1.0, miniz_oxide 0.9, sha2 0.11.1, libc 0.2.191.
2026-10-25 16:36:45 -06:00
Dylan M. Taylor a029d8aed1 build: pin craft-update to craft-libs main (495e597) (#4352)
Picks up the startup prompt without the glyphs a font may lack (storytold/craft-libs#343, #344): the close mark is painted and the version pill is ASCII, so apps that panic on a missing glyph no longer take the prompt down.

Part of tracking issue storytold/craft-libs#319
2026-10-25 17:52:32 -04:00
Dylan M. TaylorandCodebuff ee03feb81d build: pin craft-update to craft-libs main (495e597) (#4345)
Picks up the update prompt fix that draws its close mark and version pill
without glyphs a font may lack, so the prompt no longer takes the app down
when a bundled face has no ✕ or →.

Part of tracking issue storytold/craft-libs#319

🤖 Generated with Codebuff

Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-25 17:37:24 -04:00
Dylan M. Taylor e5cffe7641 Merge pull request #4233 from VoiceLessQ/fix/small-cleanups
Small fixes: MERGEFIELD in any case, 18 SonarCloud closures, one unused constructor
2026-10-25 16:45:39 -04:00
Dylan M. Taylor 7ef2633a7e Merge pull request #4298 from dylanmtaylor/feat/startup-update-prompt
feat: startup update prompt modal and direct self-updating
2026-10-25 15:53:32 -04:00
Dylan M. Taylor 57ba4b9ed8 fix(updates): localize the update status messages and format the sources 2026-10-25 15:34:12 -04:00
Dylan M. Taylor 62736d93df fix(updates): address review feedback
Wake the UI when a manual check is queued from a menu callback; the update prompt owns the keyboard while it is open (LightCraft); Download opens through the desktop URL hook (FilmCraft); the Help menu dispatches through menus::invoke (FigCraft); print jobs and comment drafts hold an install back (WordCraft); Check for Updates is a registered command (GridCraft); an install holds back while documents are unsaved.
2026-10-25 15:17:06 -04:00
Dylan M. Taylor f01a107a40 build: pin craft-update to craft-libs main (db19c37) 2026-10-25 15:03:15 -04:00
Dylan M. Taylor dd2e2c8605 fix(updates): give the update command a ui. id so the ribbon button is enabled 2026-10-25 14:37:40 -04:00
Dylan M. Taylor e3d93581b7 refactor(updates): drive the flow with craft-update's Updater
Results are read independent of the prompt, a dropped worker is an error, failures return to the prompt, and no update starts over unsaved work. A manual check during the startup check is honored.
2026-10-25 14:33:47 -04:00
Dylan M. Taylor e6954843bc build: pin craft-update to craft-libs main (b9ba47f) 2026-10-25 13:39:32 -04:00
Dylan M. Taylor 4148fb1171 refactor(updates): drive the flow with craft-update's Updater
Startup check is opt-in for the desktop app, the Windows update helper is dispatched before argument parsing, and a successful update closes through the app's own close path.
2026-10-25 13:31:27 -04:00
Dylan M. Taylor 67ffe00b32 build: pin craft-update to the dirs-free, zip 9 build
Satisfies cargo-deny: no MPL-2.0 option-ext, no zip 8 advisories, and a versioned git dependency instead of a wildcard.
2026-10-25 13:31:19 -04:00
Dylan M. Taylor a91e1b5ea4 build: merge the craft-update dependency into the existing non-wasm table 2026-10-25 13:31:16 -04:00
Dylan M. Taylor b39c1ba1a3 fix(updates): report self-update results to the prompt and finish through the app's close path
Keeps the worker's failure visible instead of leaving the prompt installing, repaints while a check runs, and no longer calls process::exit past the unsaved-work prompt.
2026-10-25 13:31:15 -04:00
Dylan M. Taylor 04121fb020 feat: startup update prompt modal and direct self-updating
Integrate `craft-update` pinned to storytold/craft-libs fe61243 to check for
updates on startup, display the standard suite update modal with changelog notes,
and support one-click in-app updating and restart.

Ref: storytold/craft-libs#319
2026-10-25 13:31:15 -04:00
Dylan M. Taylor 5dd5e8b31b Merge pull request #4241 from storytold/codex/egui-037-wordcraft-20261023
Port WordCraft to egui 0.37 with current-main editing changes
2026-10-25 13:30:14 -04:00
Martin BallandClaude Opus 5.5 4095cc3413 Security: bounded file reads, Read Aloud and macOS signing temp file (#3680, #3666) (#3877)
* #3680: Read Aloud tidies in one linear pass and cuts space-free sentences

Finding 56. tidy() repeated whole-string replacements until nothing
changed; each pass removed one level of nested empty brackets, so 40,000
pairs took ~50 s in a debug build. It is now one pass that drops a closing
bracket's empty pair as it goes, checked against the old algorithm on
20,000 generated strings. Sentences with no space to split at are cut at
MAX_UTTERANCE (1,200) characters, and each sentence is sliced from a char
vector instead of skipping from the paragraph's start.

Fixes #3680

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #3692: Paste Special reads only a regular picture file, bounded

Finding 24. A copied path naming a device such as /dev/zero reports a
length of 0, so the size check passed and std::fs::read read forever.
The path and the opened handle must both be regular files, and at most
the picture limit + 1 bytes are read. A named pipe swapped in between the
check and the open can still block the open (no portable non-blocking
open without platform flags); noted in the code.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #3692: macOS signing import decodes the certificate into a private temp folder

Finding 25. The .p12 bundle was written to a predictable name in the
shared temp folder, where a planted link could redirect it. It now goes
into a mktemp -d folder under the same temp root, removed on exit. The
keychain is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #3666: engine file reads open once and check the handle; a FIFO is refused without blocking

read_file_capped checked the path's metadata and then read the path
again, so a file swapped or grown after the check was read whole;
read_file_head opened the path with no type check, so saving to a FIFO
.xml path (the Word 2003 sniff) blocked until a writer appeared. Both
now go through open_regular_file (path checked before opening, handle
checked after, opened once) and a bounded read; read_regular_file uses
the same pieces. Tests: both helpers refuse a FIFO without blocking
and a folder; read_file_capped refuses content over the cap.

Fixes #3666

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #3692: Paste Special reads picture files through the engine's bounded read

Ultrareview finding 9: paste_picture kept a third copy of the regular-file
bounded read; it now calls wordcraft_engine::io::read_regular_file (public,
with a wasm stub).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #3666: open a checked file non-blocking so a swap to a named pipe can't hang

CodeRabbit: a path replaced by a FIFO between the regular-file check and
File::open blocked in open, before the handle check could refuse it. On Unix the
open now uses O_NONBLOCK (no effect on regular files; libc is already in the
lockfile) and the handle check refuses the pipe. The FIFO tests' cleanup writers
open non-blocking too, so a regression fails the test instead of hanging it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #3666: review — Paste Special refuses a picture file whose handle reports more than the cap before reading it

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CX1hMKX28764Lrx5moxs1o

* #3692: review — macOS signing keychain lives in the private mktemp folder too; removed if the import fails

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CX1hMKX28764Lrx5moxs1o

* #3666: review — libc comes from the workspace dependencies

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CX1hMKX28764Lrx5moxs1o

* #3680: review — Read Aloud logs a warning when its sentence cap leaves text unread

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CX1hMKX28764Lrx5moxs1o

* #3692: review — engine speech timing test gets a margin a busy CI machine can't break

tidy_is_linear_on_nested_brackets: 2 s -> 10 s. The one-pass tidy takes ~13 ms on a loaded
machine; tidy_by_replacing (the old tidy, kept in the tests) took 293 s on the same input.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CX1hMKX28764Lrx5moxs1o

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 12:32:19 -04:00
Dylan M. Taylor 6b97197f69 Merge pull request #3945 from storytold/dependabot/github_actions/actions-6dcc66fbd4
ci(deps): bump Swatinem/rust-cache from 2.9.2 to 2.9.3 in the actions group across 1 directory
2026-10-25 12:30:17 -04:00
skylar taylor-barrick ea541fe66d Merge current WordCraft main while preserving egui 0.37 migration 2026-10-25 17:30:11 +01:00
skylar taylor-barrick fe9f6dbcc9 M0: reconcile current-main dialogs and canvas changes with egui 0.37 2026-10-25 17:03:15 +01:00
ea5780d2ab Gap 9: open AES-encrypted Word files (Standard encryption) (#2628)
* Gap 9: open AES-encrypted Word files (Standard encryption)

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

* Gap 9: restore progress-doc rows lost in the main merge

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

* Gap 9: Standard package layout test built from the spec

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

---------

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:48:13 -04:00
skylar taylor-barrick 42477bd806 M0: reconcile current main and classify double-space rewrites for egui 0.37 2026-10-25 16:47:30 +01:00
Max MurphyandClaude Opus 5.5 49731f3faa #2982: File ▸ Info Custom Document Properties dialog (#2997)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:44:31 -04:00
SlavenDj 1b2f7a8c09 #1845: filter-as-you-type command search in Customize Ribbon, QAT and Keyboard pickers (#1848)
# 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 d588e0b8
# Last command done (1 command done):
#    pick 6a1268ea # #1845: filter-as-you-type command search in Customize Ribbon, QAT and Keyboard pickers
# No commands remaining.
# You are currently rebasing branch 'feat/1845-command-filter' on 'd588e0b8'.
#
# Changes to be committed:
#	modified:   crates/ui-egui/src/dialogs_keyboard.rs
#	modified:   crates/ui-egui/src/dialogs_ribbon.rs
#	modified:   docs/ui-parity.md
#

# Conflicts:
#	docs/ui-parity.md
2026-10-25 11:39:07 -04:00
MexandClaude Opus 5.5 40a7fe6be2 Make three-column header/footer presets editable tables (#2197) (#2266)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:34:23 -04:00
William de O. SilvaandClaude Opus 5.5 1489161611 fix/canvas-picture-crop-activation (#2440)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:21:53 -04:00
bf70f48bbd Bound MCP stdio request and bridge reply line reads (#3950)
* Bound MCP stdio request and bridge reply line reads

Fixes #3685

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

* #3685: an unreadable reply from the app is final, not retried

A reply that is too long (or not UTF-8) means the app already ran the
request; retrying on a new connection could run a state-changing request
twice.

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

---------

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-25 11:17:58 -04:00
NetterSilverandClaude Opus 5.5 d5f23907dc Bound total LCS work per review.compare (#4006)
Fixes #3632

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:15:42 -04:00
skylar taylor-barrick f7c49cb0f8 egui-037: reconcile main and protect IME undo and wrapped layout 2026-10-25 16:15:05 +01:00
0cb2af4f4b AutoFormat As You Type: optional "Add a period with double-space", and an AutoCorrect Options button in Options › Proofing (#2848) (#3318)
* AutoFormat As You Type: optional period with double-space, off by default (#2848)

* Test the double-space option through the AutoCorrect dialog (#2848)

* File > Options > Proofing: an AutoCorrect Options button opens the dialog (#476)

* #2848: report doubleSpacePeriod in tools.autocorrect's params doc and result

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

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:11:20 -04:00
Dmitrii KhlapovandDmitrii Khlapov 50a1c34647 #1475: Scale all style font sizes at once (#2620)
Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
2026-10-25 11:06:42 -04:00
NetterSilverandClaude Opus 5.5 b638caa2d2 Keep a document's own styles and defaults when applying a style set (#4013)
Fixes #3650

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:01:31 -04:00
Martin BallandClaude Opus 5.5 85db9cfef5 #4177: regex Replace expands capture groups (#4201)
* With Regular expressions on, Replace with reads $1…$n, ${n}, ${name}, $name,
$0/${0}, $$, \1…\9, \n (paragraph mark, splits the paragraph through the ^p
path), \t and \\, alongside the ^ codes. Named groups resolve through
meta::Regex::group_info(); missing, unknown and out-of-range groups expand to
nothing. Plain and wildcard Replace are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #4177: review — special:false keeps regex group references

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #4177: review — \$ and \^ in regex Replace keep the character as typed

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 10:53:13 -04:00
Marco Arnulfo d1db090a7c Mini toolbar: the alignment buttons mark the alignment seen on the page, as the ribbon does (#3886) 2026-10-25 10:48:42 -04:00
NetterSilverandClaude Haiku 5.5 4bf785c4cf Keep Arabic-Indic digits as typed in Arabic numeral mode (#3329)
Fixes #3259

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-25 10:44:31 -04:00
Fin WarmanandClaude Opus 5.5 a5526724aa Cover repeated DOCX style replacement across saves (#2469)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 10:43:03 -04:00
divyanshu2074 0696c55698 fix(docx): support sym hex prefixes and normalize break types and note references (#2413) 2026-10-25 10:41:23 -04:00
divyanshu2074 b37a732455 fix(formats): support negative timezone offsets and author fallback in ODT metadata (#2189) 2026-10-25 10:39:59 -04:00
SimoneandLucenx9 b0b7e6b5ea Fix Markdown code span line endings (#3804)
Co-authored-by: Lucenx9 <185146821+Lucenx9@users.noreply.github.com>
2026-10-25 10:32:31 -04:00
divyanshu2074 1b0faddfa8 fix(formats): ignore block and inline HTML comments in markdown import (#2225) 2026-10-25 10:31:01 -04:00