Commit Graph
4913 Commits
Author SHA1 Message Date
FredApps a5be0905dd Merge pull request #2649 from dotCooCoo/fix/merge-image-fields
Data merge: an image field in text places the image, not its path
2026-11-12 18:05:02 +01:00
FredApps 9aa103b3a8 Merge pull request #1843 from dotCooCoo/fix/copied-story-anchor-table-ids
Copy: copied text gets text anchors and tables of its own
2026-11-12 18:04:28 +01:00
FredApps 31d4c7f7f4 Merge pull request #2665 from dotCooCoo/feat/paste-clipboard-image
Paste: images on the system clipboard paste as embedded images
2026-11-12 18:03:55 +01:00
FredApps f3f5cd3e23 Merge pull request #2589 from dotCooCoo/fix/nested-anchored-frame-placement
Anchored text frames: place a frame anchored inside another anchored frame
2026-11-12 18:02:52 +01:00
FredApps e8276337a3 Merge pull request #2354 from dotCooCoo/fix/table-story-target
Reject ambiguous table IDs across stories
2026-11-12 18:02:30 +01:00
FredApps 811c349b39 Merge pull request #2653 from dotCooCoo/fix/pages-thumbnails-per-edit
Pages: an edit no longer renders every page thumbnail again
2026-11-12 18:01:44 +01:00
FredApps b70472bc52 Merge pull request #2647 from dotCooCoo/feat/non-rectangular-frame-inset
Text Frame Options: a non-rectangular frame shows one Inset field
2026-11-12 18:00:15 +01:00
FredApps 448ec5e468 Merge pull request #2660 from dotCooCoo/fix/cmyk-view-conversion
CMYK view: convert the blended inks to screen colours on the render threads
2026-11-12 17:59:36 +01:00
FredApps 4d86f3e34a Merge pull request #2355 from dotCooCoo/fix/mcp-dirbuilder-windows
Fix MCP temporary directory build on Windows
2026-11-12 17:58:36 +01:00
FredApps b7321d31b8 Merge pull request #2659 from dotCooCoo/feat/justification-auto-leading-single-word
Justification: the dialog sets Auto Leading and Single Word Justification
2026-11-12 17:58:12 +01:00
FredApps 6e50ee3974 Merge pull request #2650 from dotCooCoo/feat/paragraph-value-checks
Text: paragraph spacing and justification values are checked
2026-11-12 17:57:35 +01:00
FredApps 2522b78ef3 Merge pull request #2656 from dotCooCoo/fix/preflight-off-interface-thread
Preflight: check the document on a background worker, not on every edit
2026-11-12 17:56:38 +01:00
Dylan M. Taylor e2b5dbaa8a Merge pull request #2648 from dotCooCoo/fix/issue-1999
Compose: vertical Center, Bottom and Justify measure to the last baseline
2026-11-12 11:29:27 -05:00
dotCooCoo 7604db695f Copy: point copied cross-references at copied anchors in one pass
Each copied story with text anchors walked every story copied before it
to retarget their cross-references, so copying many such frames took
time quadratic in their number. The copies' cross-references are now
pointed at the copied anchors once, after the last item is copied.
2026-11-12 07:57:27 -08:00
jayzed80 5c484618ca Save: a TIFF, BMP or PSD too big for opening to inflate is stored as is, so the document reopens (#2283) (#2701)
save deflated every asset that isn't PNG, JPEG, GIF or WebP, with no size
cap, while opening refuses a deflated asset over 1 GiB or deflated entries
over 4 GiB together. An asset past either cap is now stored as is, which
opening reads at any size. Smaller assets are deflated as before, and the
zip bomb guard on load is unchanged.
2026-11-12 15:53:23 +00:00
dotCooCoo 329806477e Data merge: an explicit QR role in text is refused, and the caret follows each field
data.placeholder.add with role qr and the insertion point in text bound
the QR code to the first selected frame, which the caret was not in. It
now returns "qr placeholders bind to a frame", as a QR field there does.

A field inserted at the insertion point left the caret before its
marker, so a second field went in front of the first. The caret now
moves past the marker, as after typing.

Docs: docs/agents.md.
2026-11-12 07:45:10 -08:00
dotCooCoo c2a1543528 Copy: mark the renumber results as must-use
renumber and its helpers return false when a copy nests deeper than
MAX_COPY_DEPTH and must not be inserted. They now carry #[must_use], so
a caller that drops the result fails to build under -D warnings.
2026-11-12 07:40:29 -08:00
Adithya Shankaran 92043b4c48 Automation roots: refuse COM¹ to LPT³ and a device name before a colon (#2383)
* Automation roots: refuse COM¹ to LPT³ and a device name before a colon

is_device_name missed COM¹, COM², COM³ and LPT¹, LPT², LPT³, which Windows reserves as it does COM1.
It also cut the name only at a period, so COM1: and NUL:x were not seen as device names.

* Credit my name in the About window

* Automation roots: document the device-name tests

CodeRabbit's docstring check counts the touched tests. same_component stays without a doc comment, because #2205 deletes that function and a doc line above it conflicts.

* Automation roots: record the device-name refusal

The MCP roots description and the roadmap now name COM¹ to LPT³ and a device name before a colon.
2026-11-12 15:09:39 +00:00
dotCooCoo fad00dd646 Data merge: an image field in a table cell or a note is refused by name
With the insertion point in a table cell or a note, data.placeholder.add
with an image field returned "a hyperlink field can't go in a table cell
or a note". It now returns a message about image fields that names the
two ways on: bind the field to a frame, or pass role text to merge its
path. Nothing is inserted on the error, and role text still puts the
marker in the cell.

Docs: docs/agents.md and the command's params text.
2026-11-12 05:58:02 -08:00
dotCooCoo 375a7b48b1 Merge main into fix/merge-image-fields
# Conflicts:
#	crates/engine/src/cmd/datamerge.rs
2026-11-12 05:21:21 -08:00
autocraft-bot[bot] a17fb5d3d8 Merge pull request #2341 from Hamza0101/fix/datamerge-fields-in-tables
Data Merge: a field in a table cell goes into the cell and is filled (#2315)
2026-11-12 12:00:52 +00:00
autocraft-bot[bot] 424d08d935 Merge main into fix/datamerge-fields-in-tables 2026-11-12 11:38:19 +00:00
Dylan M. Taylor 027bbae9cb Engine: index style, tag, swatch and run lookups; bound polygon sides, Change All and spelling candidates
* fix(engine): index lookups that were quadratic in a document's styles, tags, swatches and runs

* address review: first swatch per name in book sync; bound spelling input before collecting

* address review: keep the last source style per name in book sync; bound GREP replacement bytes while generating them

* address review: write GREP replacements into a byte-bounded buffer; gate keep_last test off wasm

* merge main into fix/sec-engine-linear-lookups

* address review: make the suggestion length-cap test deterministic
2026-11-12 06:28:15 -05:00
Dylan M. Taylorandautocraft-bot[bot] ff0463e299 Exports: leave out text the page doesn't show (inherited conditions, deletions, hidden layers)
* fix(export): leave out text hidden by inherited conditions or deletion in every exporter

* address review: skip hidden frames in page text and hidden article items; first visible paragraph as nav label; read table anchor's own format

* address review: skip nonprinting frames and non-printable layers in fixed-layout page text

* Apply review fixes

- crates/epub/src/html.rs
- crates/engine/src/cmd/export/formats.rs

* Apply review fixes

- crates/epub/src/html.rs
- crates/engine/src/cmd/export/formats.rs

* address review: fixed-layout page text skips frames in inactive object states

* address review: place a threaded story at its first shown frame; skip it only when every frame is hidden

---------

Co-authored-by: autocraft-bot[bot] <354215646+autocraft-bot[bot]@users.noreply.github.com>
2026-11-12 06:28:07 -05:00
Dylan M. Taylorandautocraft-bot[bot] b7174dc92d Engine: bounded DTD validation, compound-path hole orientation
* dtd: bounded matching steps, element depth and problem count

* address review: stop DTD matching when a step charge fails; refuse hole orientation past its budget

* Apply review fixes

- crates/engine/src/dtd.rs

---------

Co-authored-by: autocraft-bot[bot] <354215646+autocraft-bot[bot]@users.noreply.github.com>
2026-11-12 06:27:59 -05:00
Dylan M. Taylorandaiongg 568f25fa9f Fonts: cap decoded names, bound outline flattening, cache fallback coverage
* fonts: cap decoded names, outline flatten tolerance by size, coverage cache for system fallback

* Apply review fixes

- crates/fonts/src/fontdb/system.rs
- crates/fonts/src/fontdb/names.rs

* Apply review fixes

- crates/fonts/src/fontdb/system.rs

* address review: cap flattened edges in has_serifs

* address review: check alias blankness before capping

---------

Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>
2026-11-12 06:27:53 -05:00
Dylan M. Taylor 665fe2a8e4 Format: a failed entry read counts against the archive budget
* format: bytes a failed entry read inflated count against the archive budget

* address review: mutate the payload bytes explicitly in the checksum test

* address review: charge a failed read to the budget it belongs to (stored vs deflated)
2026-11-12 06:27:47 -05:00
Dylan M. Taylor 26d5c8941c IDML: story export and object-style overlay in linear time, embedded image budget
* idml: story runs and marker offsets found once, object-style overlay by position, embedded image budget

* address review: saturating embedded-bytes counter

* address review: IDML export past the embed limit succeeds and warns for each image written as a link

* address review: an unlinked image is always embedded, only linked ones fall back to their link
2026-11-12 06:27:41 -05:00
Dylan M. Taylor a41fc046f3 Data merge: a record range stops expanding once the limit is met
* Data merge: a record range stops expanding once the limit or the record count is met
2026-11-12 06:27:35 -05:00
Dylan M. Taylor eb0ea78d9a Images: a WebP with an ICC chunk longer than the file is read without its profile
* Images: a WebP whose ICC chunk declares more than the file holds is read without it
2026-11-12 06:27:29 -05:00
Dylan M. Taylorandautocraft-bot[bot] 23465223bc xtask: refuse an oversized corpus archive before extracting it
* xtask: refuse a corpus archive that expands past the cap before extracting it

* address review: a within-cap answer needs tar to exit successfully

* Apply review fixes

- xtask/src/main.rs

---------

Co-authored-by: autocraft-bot[bot] <354215646+autocraft-bot[bot]@users.noreply.github.com>
2026-11-12 06:27:24 -05:00
Dylan M. Taylor f87c24a1cd PPTX export: bound the retained glyph-to-character maps
* PPTX export: keep only the last four faces' glyph-to-character maps
2026-11-12 06:27:18 -05:00
dotCooCoo ed9980fec2 Paste: params text gives the pasted image's size as one point per pixel
edit.pasteImage sizes a new frame as File › Place does, which reads a
raster at one point per pixel and does not read a stored resolution.
The params text and the comment said otherwise.
2026-11-12 00:39:11 -08:00
dotCooCoo 346a0b24a2 Paste: objects copied over empty clipboard text paste from the menu
With a native menu, Copy saved the clipboard's empty text as the copy's text, so the next Paste took the older image, which the paste then skipped, and nothing was pasted. Empty text now counts as no text at the copy, as it does at the paste.
2026-11-12 00:12:21 -08:00
dotCooCoo 915be8561e Paste: an image past the size limit is refused before its pixels are copied
ClipboardImage::from_color_image checks the size before it copies the pixels, so an image egui delivers with Ctrl/Cmd+V that is over 64 million pixels is not copied before the paste refuses it.
2026-11-12 00:05:58 -08:00
dotCooCoo c9cc76e6ad CMYK view: the conversion returns the number of bands it converted
With more render threads than bands of 32 rows fit evenly, the rows split
into fewer bands than requested, and the returned count was the requested
one. It is now the number of bands converted.
2026-11-11 22:45:44 -08:00
dotCooCoo bd2bea1ae5 Merge feat/paste-clipboard-image 2026-11-11 22:07:17 -08:00
dotCooCoo b1a514fc51 Paste: ui.paste checks the image's size before decoding it
ui.paste {image} refuses base64 longer than the 256 MB file limit
before it decodes the data, with the same check edit.pasteImage uses.
2026-11-11 22:05:16 -08:00
dotCooCoo 8463cef4a9 Paste: refuse damaged clipboard images and journal one entry per paste
- edit.pasteImage decodes the whole raster before it stores the image,
  so a file whose pixels are cut off after a whole header is refused.
- edit.pasteImage is the only journal entry for a paste; the file.place
  it runs no longer adds a second one, so a replay places the image once.
- Empty clipboard text beside an image counts as no text, so Edit >
  Paste pastes the image.
- With a native menu, a pasted image event is ignored while the
  clipboard still holds what it held when objects were copied here.
2026-11-11 21:59:10 -08:00
dotCooCoo eda934fff0 Compose: vertical justification keeps moved lines inside a shaped frame
Center, Bottom and Justify moved the lines of a shaped frame without
testing them against the outline, so in a frame that narrows towards the
bottom a line set in a wide band ended up crossing the outline. Each moved
line's slot is now tested against the outline over its new band, as when
the line was fitted, and the text goes only as far down as every slot
fits. In a frame that narrows and widens again, the search scans the
rooms from the most down (every point, at most 512 steps) before halving,
so the text can still reach a lower part past a narrow waist.
2026-11-11 21:54:27 -08:00
dotCooCoo bdabdc8155 Preflight: show a pending first check as checking, and rebuild document indexes on grid changes
- The status bar and the Preflight panel show a gray light and "Checking" until the active
  document's first check ends, instead of a green "No errors".
- The cross-reference and running-header indexes are keyed on the baseline grid and the font
  scope as well, so a change to either builds them again, in a cache and in a cache over it.
- The test helper that waits for the preflight worker fails when the worker ends without a result.
2026-11-11 21:51:37 -08:00
autocraft-bot[bot] 6b9c47fdb2 Apply review fixes
- crates/ui-egui/src/app/clipboard.rs
- docs/egui-037-migration-plan.md
2026-11-12 05:37:36 +00:00
autocraft-bot[bot] 2e1d17e1fa Apply review fixes
- crates/ui-egui/src/preflight_worker.rs
2026-11-12 05:32:14 +00:00
.CooCoo 6fff5328eb Tests: type.align refusal cases name the check that refuses each (#2662)
Follows #2645. Its test said a misspelled key used to apply Align Left.
Only empty params and a bare string did; the parameter check already
refused a misspelled key, and the value parser refused an unknown
value. Each case now asserts the refusal message it gets.
2026-11-12 04:52:41 +00:00
dotCooCoo 630b5dfc43 Paste: images on the system clipboard paste as embedded images (#2204)
Paste ignored a bitmap on the system clipboard: a screenshot or an image
copied in a browser had to be saved and placed. Paste now places it.

- edit.pasteImage {base64, name?, spread?, at?} embeds the image in the
  selected empty frame, or in a new frame centered on `at` at its stored
  resolution (72 ppi when none) and at most 60% of the page width, as
  File > Place sizes it. Save and reopen and IDML export keep the pixels.
  Images over 64 million pixels and names without an image extension are
  refused.
- Ctrl/Cmd+V pastes the image egui delivers with no text, and Edit >
  Paste reads the clipboard's bitmap, or the first image file of a copied
  file list, when there is no text or the text is only an address.
- The menu read waits at most 1.5 s on its own thread, with one read in
  flight at a time.
- With a native menu, objects copied here still paste as objects until
  the pasteboard's change count shows a newer copy.
- ui.paste takes {image} for the control channel.
2026-11-11 20:50:24 -08:00
dotCooCoo b73c21db37 Data merge: a file that is not an image does not hide a later image candidate
The image search stopped at the first file that could be read and
checked whether it decodes afterwards. A non-image file at an earlier
candidate (the drive root, or beside the data file) then hid a valid
image beside the data file or the document, and the field was reported
missing. The decode check now runs inside the search, so only an image
ends it.
2026-11-11 20:36:39 -08:00
dotCooCoo c69db89862 Justification: Auto Leading stores the shown percent, and the current choice is no edit
The Auto Leading field shows whole percents, and it now stores the
whole percent it shows, so a typed 500.4% (shown as 500%) is accepted
as 500% instead of being refused. Picking the Single Word
Justification the paragraphs already have is no longer an edit, so OK
adds no undo step for it.
2026-11-11 20:06:28 -08:00
dotCooCoo 27963d6d05 Justification: the dialog sets Auto Leading and Single Word Justification
Type > Justification and Paragraph Style Options > Justification now show
Auto Leading (0% to 500% of the type size) and Single Word Justification
(Align Left, Align Center, Align Right, Full Justify). Both fields show the
selected paragraphs' values, or blank where they differ, and OK writes
autoLeading and singleWordJustify only when they were edited. An Auto
Leading outside 0% to 500% keeps the dialog open with the reason.
2026-11-11 19:45:30 -08:00
dotCooCoo 9c4c3730ab CMYK view: convert the blended inks to screen colours on the render threads
In the CMYK blend space view (Proof Colors off) every render converted
each pixel of the ink passes' area from the blended inks to a screen colour
on the calling thread, through a 16-entry lookup per pixel. With render
threads it now converts bands of rows on that many threads at once, at
least 32 rows a band. The colours are the same; the Wasm build and
single-threaded renders convert on one thread as before.
2026-11-11 19:42:30 -08:00
dotCooCoo ee69d5ac39 Preflight: the worker keeps its compositions out of the interface thread's cache
The worker checks the document state it was given, which is often one
edit behind the interface. It composed that older state into the shared
composition cache, replacing the interface thread's composition of the
current state, so the next frame composed the edited story again (about
14 ms per edit for a 10-page story).

Cache::over makes a cache that uses another cache's compositions of the
same state and keeps whatever it composes to itself. The worker checks
with one over the interface thread's cache, keeps it for the next check
of the same document, and drops it after a minute without jobs.

With no active document, the job waiting for a busy worker is dropped,
so it no longer keeps a closed document in memory until another
document opens.
2026-11-11 19:42:03 -08:00