Found while testing crates/geom/src/units.rs:~147 (Unit::ruler_ticks, the `while major * zoom < 50.0` loop)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/mcp/src/server.rs:62-64 (Server::serve)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A duplicated text frame holding an anchored placed PDF leaves two placements sharing one ItemId, so the raw update count exceeded the variant count and a correct export failed. The guard now checks that every mapped id was reached. Replaces the mismatch test with a duplicated-frame export regression.
A column rule ran from the top of the columns to their bottom, so a frame
that the text only half fills drew its rules down to the empty bottom of
the frame. InDesign draws them from the top line's ascent to the bottom
line's descent. column_rule_rects now takes that extent from the frame's
lines, and the top and bottom insets shorten the rule from there. A frame
without lines draws no rules. Existing documents draw their column rules
at the new length, on screen, in PDF and in PowerPoint export.
The ruler's space is allocated before the text editor, so toggling it
moved the editor's automatic widget id, and the editor lost its focus
and caret. The editor now has a fixed id.
The shared table's Spanish column held the English label. It now reads
"Mostrar/ocultar regla de profundidad", and a test checks that every
interface language translates the label.
* Styles: renaming a style keeps its Export Tagging
Renaming a paragraph or character style, or moving it into a style
group, moves its Export Tagging to the new name. Deleting a style drops
its tagging and leaves the replacement's own tagging unchanged.
* Styles: a paragraph style can't be renamed onto another style's name
* Styles: a refused rename says the name is taken and shows the General section
Renaming a paragraph or character style onto a name another style has
now says so ("a paragraph style named `Body` already exists"); empty
or bracketed names keep the generic message. The Paragraph Style Options
dialog switches to General, where the name field is, when the rename is
refused. Paragraph style names are trimmed like character style names,
and a renamed style never picks up an export tag left under its new name.
* Styles: the rename test's stale tagging takes the Split Document field
* ROADMAP: date the style rename line 2026-10-24
* Search: Delete Workspace is left out of Quick Apply and command search
It needs a saved workspace's name, which a search entry can't supply,
so choosing it there failed. The application bar's workspace menu lists
the saved workspaces to delete.
* Search: leave out the interface commands that fail or reset a setting there
Quick Apply and the application bar's search ran their entries without
parameters. Commands that need a workspace, a command and shortcut, a
menu item, a panel, a window edge, an app page, a recent file, or a
swatch or color group failed when chosen there. Interface Color Theme
and UI Scaling switched to the dark theme and 100%, Workspace switched
to Essentials, and Reset Shortcuts cleared every custom shortcut without
asking. Search leaves all of them out; each stays in the menu, panel or
dialog that gives it the value.
* Search: the flattener preset, Screen Mode, Zoom To and the Task Bar pin stay out of Quick Apply
The parent-page regression covers a placement a page inherits. The other placement the export
walks reach is an object anchored in a story: the IDML copy gets a variant that shows every
layer, an external-only copy is refused, and PDF/A-2b rasterises it and warns. The nested-story
regression that used to cover this case also asserted placements anchored inside a table cell and
a footnote, which this pass does not reach; this one keeps the anchored case alone.
Both exports walk Document::placed_items: document and parent spreads, groups, and the objects
anchored in a story. That is the walk the parent-page and anchored fix introduced. The
nested-story traversal (table cells, notes, endnotes), Document::update_placed_items and the
fail-closed refusals that went with it are not part of it: that is the traversal change on its
own, not the placements this pass carries. update_items keeps its reach, so the two exports clear
the choice where the placement actually is again.
A choice anchored inside a table cell's or a note's text therefore stays on the document and is
not carried into the embedded IDML copy, as on main; the refusal that turned that silent
difference into an export error goes with the traversal it guarded, since asking the walk's own
predicate it could never fire. The stale-field half keeps: has_applicable_pdf_layer_overrides
still asks for a graphic whose asset is a PDF, so relinking a placed PDF to an image no longer
makes the package report name a choice that does not exist.
Tests: the nested-placement regression and the relink integration test of the removed refusal
go; the parent-page regression, the stale-field predicate test and the format 4 cell-only reader
test stay. The comments no longer claim every placement counts.
Graphic gained an optional layer_options field, so the test-only literals in the PDF
crate and in the engine's optional-content support need it. No behaviour changes.
The workspace file guard scans test modules too when they are declared `pub(crate) mod` (it only
skips a plain `mod`), so a temp file written inside pdflayers.rs' tests failed
no_crate_touches_the_file_system_outside_the_checked_readers. The unit test now builds the state a
relink leaves behind - layer fields on an item whose asset is an image - and asserts the refusal
predicate ignores it while all three exports run. The user path (a real links.relink to a PNG) moves
to tests/pdf_optional_content.rs, where the guard exempts fixtures written by test files.
Every craft-libs crate and the Krilla/Hayro patches use one revision, which
also vendors hayro-postscript. Clipping text paints nothing in the PDF bounds
device; its clip arrives through push_clip_path.
Pin the final egui, winit and shared UI revisions and reconcile current main.
Preserve document-epoch input and screenshot boundaries, host action ordering,
and Windows path regression coverage. Add click/End batch characterization.
Validation: all nine Linux CI stages pass (3230 tests, zero failures); Windows
CI and bounded native editing workflows pass on the same production source.
The Control panel's Font Size, Leading and Baseline Shift and Character •••
Baseline Shift still used NumField::number with " pt", which read 13Q as
13 pt. NumField::number now makes a points field for the " pt" suffix, so
no point field can miss it; with_suffix is gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013phQ3ekq6uGBEWD6FjFYG2
The Story Editor has a vertical depth ruler between the style column
and the text. It is marked in the document's vertical ruler units with
how deep the story's text fills its frames, counted through its
columns and threaded frames, and it is shaded down to the overset
point. Paragraph spacing adds to the depth. Lines set side by side, in
the sub-columns of a split paragraph or on both sides of a wrap
object, count once. Where several marks fall on one editor row, only
the deepest is drawn. A red line crosses the text, and the ruler when
it shows, above the first character that does not fit.
View › Story Editor › Show/Hide Depth Ruler (view.storyEditorDepthRuler)
shows or hides the ruler in the Story Editor, for every story opened in
it. The ruler is shown by default, and the setting is saved with the
preferences.
a_missing_link_shown_by_its_preview_is_still_reported builds its link
under std::env::temp_dir(). On macOS and Linux that returns TMPDIR as
set, so a relative TMPDIR gave a relative link, which document_path
refuses in a document without a path, and the test failed with
"(the path is not valid)". The test now passes the temporary folder
through std::path::absolute first. The preflight code is unchanged.