The document keeps its outlines sorted by image and threshold, and the
lookup uses a binary search. The data merge test now checks that the
merged document has the image's outline, and that a bounding box wrap
leaves the same caption overset.
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.
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.
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.
* 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.
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.
* 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
* 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>
* 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
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.
Before, an image with no transparency wrapped like its frame, so a smaller image or one moved within its frame kept text out of the frame's empty part.
- 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.
- Editing a style's paragraph style restyles each paragraph still in
the old style; a paragraph given another style keeps it.
- Renaming a style updates objects anchored in table cells and notes.
- corners refuses keys other than shape, size and corners.
- each traced Alpha Channel outline has a serial number, and the composition signatures include the outlines in use, so a relink or link update that changes only the image data no longer leaves text laid out around the old image
- a wrap with the default alpha threshold is saved without it, as before thresholds were stored
- docs/typography-parity.md says Alpha Channel contours follow the image's visible pixels
style.object.edit updates the attributes and paragraph styles of text
frames anchored in stories, table cells and notes, as IDML import
places them, as it does for frames on spreads.
When a style that set no stroke gains one, its frames with no stroke and
its drawn shapes still carrying the default 1 pt black stroke take it. A
text or graphic frame with its own stroke keeps it.
- style.object.create and edit refuse a fill, stroke or gap swatch the
document lacks, and a fill or stroke key that is not a setting of it
(a misspelled "wieght" no longer succeeds without a change).
- fromSelection must be true or false.
- Editing a style's Text Frame General Options updates each option a
frame still shares with the style, so a frame's own inset stays while
a new column count reaches it.
- style.object.create and edit refuse corner sizes outside 0-10000 pt
instead of clamping them.
- IDML import: a style that turns Stroke & Corner Options on without
corner attributes of its own takes all four corners from the styles
it is based on.
- An object style's text frame options set the columns, insets,
vertical justification, paragraph spacing limit and Ignore Text Wrap.
A frame keeps its auto-size, baseline, column rule and Type on a Path
settings, and follows an edit of the style while its General options
match the style's.
- textFrame refuses keys outside the General options, takes one number
for all four insets, and checks the values the call gives.
- Applying a style that changes nothing records no undo step.
- The dialog's Paragraph Spacing Limit reaches the style.
- IDML import: a style's Text Frame General Options take the settings
its TextFramePreference leaves out from the styles it is based on
(by id or bare name), skipping styles that turn the category off.
- i18n: Hungarian and Swedish rows for the object style dialog; the
duplicate Brazilian Portuguese rows are removed.
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.
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.
- Align Left, Center, Right, Justify Left, Justify All Lines and
type.align leave the document and the undo list alone when every
target paragraph already has that alignment as its own value.
- On the Mac, Em Space, En Space and Current Page Number from the menu
bar also do nothing while Quick Apply or a dialog is open, an input
method is composing or a canvas context menu is open, the cases that
stop the window's own shortcuts.
- Tests for both, and for Justify All Lines across threaded frames,
over a paragraph style, through IDML export and import, and with
parameters it does not take.
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.