chore: sync upstream (869 Commits) #15

Merged
alf merged 869 commits from chore/sync-upstream-20261031 into main 2026-10-31 16:53:02 +00:00
Owner

Upstream-Sync von upstream/main (869 Commits). Fast-Forward.

Upstream-Sync von `upstream/main` (869 Commits). Fast-Forward. - ea214dd4 Merge pull request #2070 from aiongg/docs-tidy - 7cdc47b5 Merge pull request #2072 from aiongg/update-result-dialog - 153d232a Merge pull request #2052 from texjer/feat/import-warning-show - 99f90cbe Merge storytold/main into PR #2052 - c1561bdf Merge pull request #1239 from seanth/xref-edited-text - 74b9944b Merge storytold/main into PR #1239 - fd7a9064 Merge pull request #2057 from seanth/running-header-placeholder - 06a5199e Merge storytold/main into PR #2057 - ce55968f Merge pull request #1232 from seanth/parent-page-display - 5f656b25 Merge storytold/main into PR #1232 - 379a51fb Merge pull request #2055 from ZIDAN44/fix/1964-frame-size-units - 400e96c2 Merge storytold/main into PR #2052 - faa2bf50 Merge storytold/main into PR #1239 - 8ff43f55 Merge storytold/main into PR #2057 - 4479555a Merge storytold/main into PR #1232
alf added 869 commits 2026-10-31 16:53:00 +00:00
Chris Nielsen's "Numbering Page Sections" reads the Pages panel all along:
InDesign labels each spread ("2–3", "2, 1" where a section starts inside
it, "8, A", "ii–iii"), puts a small triangle over each section's first
page, and the panel scrolls to the page selected ("the pages panel jumps
down there", 6:46). DesignCraft named each page under it ("2 1") and drew
its triangle over the spread in view.

- One label per spread (spread_label): a range with an en dash for pages
  numbered on in one section, the names apart when a section starts inside
  it. Positions under absolute numbering. A blue badge marks the spread in
  view; a click on the label goes to the spread.
- A triangle above every page that starts a section (page 1 included).
- The panel scrolls to the spread of the page in view when that page
  changes.
- Page thumbnails are named for screen readers ("Page 1").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chris Nielsen's "Numbering Page Sections" (4:43): with page 3 selected,
the Pages panel menu's Numbering & Section Options opens InDesign's New
Section window: Start Section checked, Automatic Page Numbering chosen
and 1 offered in Start Page Numbering at, which stays editable. The window
here was titled Numbering & Section Options, Start Section was off and
the field showed the page's current number, greyed out.

- Opened on a page that doesn't start a section, the window is New
  Section: Start Section on and 1 offered; on a section's first page it
  is Numbering & Section Options, as before.
- Start Page Numbering at and Start Chapter Numbering at stay editable;
  typing a number chooses that option.
- "New Section" translated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chris Nielsen's "The Adobe InDesign Toolbox" (10:10): with the White
Arrow he clicks outside, then presses on a frame's corner and pulls it up,
turning the rectangle into a lopsided triangle. DesignCraft only looked for
anchors on objects already selected, so the press fell through to moving
the whole frame.

The Direct Selection tool now also looks at the anchors of the object
under the pointer: on one, it selects the object and drags that point, in
one undo step. Elsewhere on the object it still drags it whole; Shift-
click still toggles the selection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#563 composed the story again with its objects where the previous pass put them, up to four
times. In a long story whose objects move between frames from one pass to the next (Learn Skills
Daily's 03_HP_LongDoc_Class, 79 pages), that never settled: stale wrap areas pushed headings into
the next frame. Now the composer places a custom or above-line object when its anchor line is set
and the lines after it wrap it in the same pass, as in InDesign.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Direct Selection click on an image left the selection alone when its frame
was already selected with the Selection tool, so Delete removed the frame
and the image together. The click now switches to the image inside, and
Delete leaves the empty frame (Fixes #1124).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When nothing is selected, display the new-object fill and stroke supplied by #1081. Existing selection targets retain their path. Exercise a real spectrum click, existing/new shape colors and undo in the whole-window regression.

Co-Authored-By: GPT-6 Astra <noreply@openai.com>
Use the existing explicit-null deserializer for Ruby and Kenten sizes, tints and stroke weights, plus the automatic list tab. Extend native ZIP and legacy JSON inheritance regressions for local and named-style clears, absent overrides and explicit values. Found when a no-edit course-book roundtrip discarded eight CJK defaults.

Co-Authored-By: GPT-6 Astra <noreply@openai.com>
On a parent page a running-header variable has no page to read, so it
composed blank; it now shows <variable name>, as the header's placeholder.

While parents were edited, document frames weren't laid out and fell back
to the identity canvas transform, so their hidden characters (a flood of ¶),
spelling squiggles and other overlays were drawn over the right parent page.
Items on spreads that aren't shown now have no canvas transform.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
InDesign writes a TOC style entry's separator with the built-in prefix (`Separator="$ID/^y"`, the right indent tab)
and its FormatStyle / PageNumberStyle / SeparatorStyle as `<Properties>` children, not attributes. The importer kept
the prefix as text (entries read "Welcome$ID/<tab>3") and never found the entry styles, so a regenerated TOC lost its
entry paragraph style and page-number character style.

- names::toc_separator_in strips `$ID/` before decoding.
- toc_of reads FormatStyle, PageNumberStyle and SeparatorStyle with `prop` (attribute or Properties child).
- tests: a TOC style written as InDesign writes it imports its separator, entry style, page-number style and title style.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign keeps text typed over a cross-reference's generated text (until the
cross-reference is updated), with its page number still live. The IDML
importer dropped that text and generated it again from the format, so a
credits list whose format reads "Last, First. ... YYYY. Volume X, issue Y."
showed those placeholders instead of the names and dates typed in.

- CrossRef gains `text` (edited text, `<pageNum />` for the live page) and
  `page` (the page last shown). Import keeps saved text that no longer
  reads as its format produces it; export writes it back with InDesign's
  XRefPageNumber variable. Setting a format drops the edits, as InDesign does.
- Edited text whose destination is gone shows its saved page, not "??".
- Spaces in a cross-reference's text are word spaces the line may break at
  (it was set as one unbreakable piece, so long ones broke mid-word).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
Show the existing trash icon on selected or hovered custom Saved cards and route it through file.deletePreset. Keep the factory card protected, prevent the action from selecting or creating a document, and retain the configured preview. Cover both selected and hovered-card clicks in the whole-window regression.

Co-Authored-By: GPT-6 Astra <noreply@openai.com>
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/idml/src/tests.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The readout beside the cursor while drawing or measuring uses a new
readout_bg token, InDesign's #a8a8a8 with white text as measured from the
tutorials' frames. High Contrast keeps it black.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Points selected with Direct Selection title Properties "Anchor Point(s)"
and show Transform, Appearance, Convert Points and the Delete Point(s)
quick action, as InDesign does. path.deletePoints removes the selected (or
given) points of several paths in one undo step. The Convert Point glyphs
are redrawn after InDesign's: the anchor on a corner or a curve with its
handles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rows show a crossed pencil on the swatches that can't be edited ([None],
[Registration], [Black]), the colour type (process halftone or spot disc)
and the colour mode (CMYK, RGB, Gray, or the [None] and [Registration]
glyphs), drawn in code, in place of a lock and "CMYK" text. The Tint field
reads 100 with nothing selected, as InDesign's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
object.clearFittingOptions puts the frames' auto-fit, crop amounts and
reference point back to their defaults and leaves the picture where it is.
Object > Fitting (and the context menu) groups the proportional fits, the
frame and content fits, Clear Frame Fitting Options and the dialog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One glyph each for the selection, the key object, the margins, the page and
the spread, drawn in code, so the button tells what the objects align to.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As InDesign's Effects dialog › Blending › Mode: the shadows start Multiply
and the outer glow Screen in white; the renderer blends each with what's
behind it, the commands take mode, IDML reads and writes the drop shadow's
BlendMode. Effects saved before read Normal, as they were drawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A circle whose radius points where the light comes from; a click or drag on
it sets the angle (0 degrees to the right, counter-clockwise).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dialog follows InDesign's: General, Column Rules, Baseline Options, Auto-Size; on General,
framed Columns (Number and Width, Gutter and Maximum, Balance Columns), Inset Spacing (Top and
Bottom, the link, Left and Right) and Vertical Justification (Align, Paragraph Spacing Limit),
with spinner fields. With Fixed Number, Width shows each column's width as the number, gutter
and insets change.

Preview shows the options on the page while the dialog is open (redone as fields change); Cancel
puts the frames back, OK sets them once as one undo step.

Vertical Justification › Justify honours the Paragraph Spacing Limit: the extra space goes
between paragraphs, up to the limit each, and what is left spreads over every line (all of it,
with no limit, as before). object.textFrameOptions takes it as paragraphSpacingLimit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A paragraph rule has InDesign's Type: solid, the thick/thin stripes, dashed, dotted, straight hash,
wavy, or a stroke style of the document. Composition draws it as that shape in the rule's box
(dashes and dots as boxes and circles, stripes, waves and hashes as their outlines), with Gap
Color and Gap Tint underneath; a pattern that can't be laid out draws solid. Keep In Frame keeps a
rule above the first line of a frame inside the frame.

The Paragraph Rules page (paragraph style options and the Paragraph Rules dialog) is laid out as
InDesign's: Weight and Type, Color and Tint, Gap Color and Gap Tint, Width and Offset, Left and
Right Indent, Keep In Frame. IDML reads and writes RuleAboveType/RuleBelowType, the gap colour and
tint, and KeepRuleAboveInFrame. A rule's new settings at their defaults stay out of the JSON.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New Paragraph Style with text selected starts from it, as InDesign's: Based On [No Paragraph
Style] and every setting of the text that differs from it, with Apply Style to Selection (on), so
OK gives the paragraph the new style. General has Next Style ([Same style] or a style) and Reset
To Base (the style keeps nothing of its own; edits made in the dialog still apply). Basic
Character Formats is laid out in two columns as InDesign's: the font, then Size | Leading,
Kerning | Tracking, Case | Position.

style.paragraph.edit honours nextStyle (string, or null for [Same style]); it was described but
ignored. It takes resetToBase.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New Character Style with text selected starts from what the text has of
its own over its paragraph style (its character style's attributes and
its overrides), as InDesign's "[None] + Bold + color", and Apply Style to
Selection (on) gives the text the new style with no override left. A new
style's dialog is titled New Paragraph Style / New Character Style.
type.selectionAttrs reports the text's own character attributes as
ownChars. Found in the Learn Skills Daily course, chapter 22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
find.change takes a Change Format: charStyle and paraStyle as well as
the character attributes (attrs) it took. With a Change Format and an
empty change, the found text stays and is only formatted, as InDesign
does; without one an empty change still deletes. The style-apply code of
style.paragraph.apply / style.character.apply moves into helpers that
find.change shares.

The Find/Change dialog has InDesign's Change Format box, with Specify
Attributes (opening Change Format Settings over Find/Change: Style
Options, then the character sections of Character Style Options) and
Clear. An info icon beside Change to says an empty Change to keeps the
text. Found in the Learn Skills Daily course, chapter 22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
find.find, find.next and find.change take findFormat {charStyle?,
paraStyle?, chars?}: only matches whose text has the format all through
are found, and with an empty find, each stretch of text with it (the
longest runs, one per paragraph). Resolved attributes are compared to
within rounding; unknown styles and attributes are refused. A changed
Find Format restarts Find Next.

The dialog has InDesign's Find Format box above Change Format, with its
ⓘ beside Find what; Find Format Settings is the Change Format Settings
dialog opened for finding. Found in the Learn Skills Daily course,
chapter 22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
find.change takes found: true for Change: only the text Find Next found
changes (the selection, while it's still a match of the search in its
domain), it stays selected, and the search keeps its domain so the next
Find Next goes on after it. A selection that isn't a match changes
nothing and makes no undo step.

The dialog has InDesign's Change and Change/Find buttons, off until text
is selected, and its Search list reads Document, Story and Selection.
Found in the Learn Skills Daily course, chapter 22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As in InDesign, a double-click on Properties › Appearance's Fill or
Stroke chip opens the Color Picker with that colour (a click still opens
the swatches). For selected text, its own Fill and Stroke chips open it
for the text. Found in the Learn Skills Daily course, chapter 23.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As in InDesign, a click on the name of the swatch picked already (a slow
double-click) turns the name into a field: Enter renames the swatch
(swatch.options, so everything that uses it follows), Escape keeps the
name. A double-click still opens Swatch Options, and the special swatches
keep their names. Found in the Learn Skills Daily course, chapter 23.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The eyedropper beside the hex code works as InDesign's: pressed and
dragged onto the page, it takes the colour shown under the pointer when
let go (one device pixel rendered as the canvas renders it, over the
paper); off the pages it takes nothing. Found in the Learn Skills Daily
course, chapter 23.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With nothing in the place cursor there's no thumbnail to show, so the
cursor is the crosshair before a press too, as it already was while
dragging. (Review.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The place cursor draws a frame from 3 points, but the canvas sent Drag
events only once egui started a drag (at max_click_dist, 6 points). A
release in between placed a frame the preview never showed. With the
place cursor, the canvas now follows the pointer from 3 points. (Review.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With a gradient fill or stroke, the Color panel showed "[None] — choose a
colour on the ramp", and a spectrum click replaced the whole gradient with a
flat colour. As in InDesign, it now shows the stop selected in the Gradient
panel (the stop before a selected midpoint) with its values, and its
C/M/Y/K or R/G/B sliders and spectrum recolour that stop, keeping the others.

Found in the Learn Skills Daily course, chapter 24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While a parent was shown, the status bar's page box and Properties › Page
still read page 1. As in InDesign, they now name the parent ("A-Parent"),
and their lists have the parents after the pages: choosing a parent shows
it, choosing a page leaves the parents for that page.

Found in the Learn Skills Daily course, chapter 25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Insert Pages… opened the generic command form (Count, a 0-based After
index, a parent id). It now opens InDesign's dialog: Pages; Insert After
Page, Before Page, At Start of Document or At End of Document, with the
page by name; and Parent ([None] or a parent). It is set to the page in
view (or the page right-clicked) and that page's parent.

`layout.pages.insert` takes `before` (0: at the start of the document);
`after` and `before` together are refused.

Found in the Learn Skills Daily course, chapter 25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spell checker uses the Moby Hyphenator II word list, which lacks some
very common short words (we, us, if, Mr, pm, vs) and most computer and web
vocabulary (email, online, website, database, desktop, download...).
Contractions typed with a typographer's apostrophe (don’t, we’re), which
Use Typographer's Quotes produces by default, were looked up with the
curly apostrophe and flagged too. Dynamic Spelling underlined most words
of an ordinary sentence.

`known` now reads U+2019 as a straight apostrophe (also in the user
dictionary) and accepts a short sorted list of such common words, with
the existing inflection rules applied to them.

Found in the Learn Skills Daily course, chapter 26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Preferences › Interface held only UI Size, and the interface theme could be
changed only from Window › Interface Color Theme. As in InDesign, Interface
now has Appearance, with a Color Theme swatch per theme (a click shows it at
once, Cancel goes back to the theme Preferences opened with), and Panels,
where Tools Panel sets a single or double column. UI Size moves to a UI
Scaling section of its own, as in InDesign's list.

Found in the Learn Skills Daily course, chapter 26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Number of Recent Items to Display read "20.0": its field's drag speed of
0.2 gave it a decimal place. It now shows "20", as InDesign's does.

Found in the Learn Skills Daily course, chapter 26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Package… went straight to a folder picker and packaged with fixed options.
As in InDesign it now opens the Package dialog: Summary counts the fonts,
links and images and inks the package carries (a warning where some are
missing or modified), and Fonts, Links and Images and Colors and Inks list
them, with Show Problems Only. Create Printing Instructions leads to the
Printing Instructions dialog (contact, company, address, phone, fax,
email, instructions), whose text goes into the package's Instructions.txt;
Include IDML and Include PDF (Print) choose the copies the package carries.

Found in the Learn Skills Daily course, chapter 27.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Package dialog's Include PDF (Print) gets a PDF Preset, as InDesign's
Select PDF Preset: the Export PDF presets, the last one used first. The
packaged PDF always had the default settings.

`file.package` takes `pdf: {…file.exportPdf options}` besides true/false,
read with the same `export::options` before anything is written, so bad
options leave no partial package. The Export PDF dialog's field-to-params
code is shared (`pdf_export_params`, `pdf_preset_params`).

Found in the Learn Skills Daily course, chapter 27.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The course's chapter 40 (Applying Borders to Styles). Paragraph Style
Options › Paragraph Border and Paragraph Shading get InDesign's "Make all
settings the same" link for the stroke weights, the offsets and the
corners. It starts on when the four are the same, so a side typed in sets
all four; with the link off a side is set alone, as the lesson gives a
border only a thick left side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A full gap tint is left out of the rule's JSON, so the field read nothing
even after a Gap Color was chosen. It now reads a missing gap tint as
100%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`layout.pages.insert` refuses `after` and `before` given together (null
counts as given) and a placement that isn't a page index, instead of
inserting at the default position; the default applies only when
neither is given. The dialog sends the page its menu shows (a page past
the end is the last). The dialog title is in the shared table, and
Georgian "Before Page" reads "გვერდის წინ".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dialog notes that the created style exists (so a second OK edits it)
before Apply Style to Selection runs, so a failure there can't lead to a
duplicate style. The Justification check's doc comment is back above
its function.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The Find Format's character attributes are read through
  `CharAttrs::set_json` and matched as the document writes them
  (camelCase keys, its number forms), so `font_style` finds what
  `fontStyle` finds. A null attribute asks for nothing.
- Values compare numbers within rounding inside objects and lists too, so
  a 14 pt leading written as `{"kind": "points", "value": 14}` matches.
- `FindFormat::spans` passes over a story's runs once, with a cursor that
  only moves forward across the paragraphs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change used to accept a selection only when Change All's matches (from
the start of the target) included it. Find Next can select text those
never produce: the rest of a Find Format stretch from a caret inside it,
or an overlapping match ("aa" in "aaa" from the second a). Both commands
now share one definition (`Search::found_edit`). Without a pattern, a
selection inside one stretch is a match; with one, the pattern's match
from the selection's start must be the selection, and a GREP replacement
is expanded for that match (`Grep::replacement_at`).

"Selection" has a row in the shared table (Spanish and Chinese fell back
to English); the French entry moves there from `fr.rs`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- `screen_post` holds what the canvas does to a render before showing it
  (Proof Colors, the composite ink-limit preview). The texture and the
  eyedropper's one-pixel sample both go through it, so with either view
  on, the eyedropper takes the colour on screen.
- The picker's OK uses the footer's padded "  OK  " key, which every
  catalog has (Chinese showed "OK").
- "RGB Color Space View", "Lab Color Space View", "Add CMYK Swatch" and
  "Added swatch" are in the ar, cs, it, ka, pl, pt-br, ru and uk
  catalogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Tools Panel menu's Single Column fell back to English in these
catalogs. Russian Double Column reads "Две колонки", the table's word for
layout columns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test checked only that the count was whole, so another default would
pass. It asserts 20, InDesign's default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- When `file.package` fails, the Package or Printing Instructions dialog
  comes back with its options and instructions, and the status line says
  why. Before, they were lost.
- The Colors and Inks table heads its kind column with the "Type:" key
  (without its colon). The "Type" key is the menu's and reads Text in
  most languages.
- `app.packageDialog` with no document open is an error rather than a
  silent success.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
file.package now writes its PDF through export's `pdf_report`, so a preset's
transparency flattening, the effects and hidden-layer rasterising, the blend
space, the view options and the transitions all reach the packaged PDF.
A `pdf` that is neither a switch nor export options is refused, as is a bad
flattener, before anything is written. Georgian: the printing term for spot
inks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clicking "Make all settings the same" back on gives the four weights or
offsets Top's value, and the four corners Top Left's size and shape, so OK
never saves sides that differ under a closed link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ending a rename by clicking another swatch keeps that swatch picked (for
Delete Swatch) instead of the renamed one. A click on another swatch while
the rename's double-click wait runs cancels the rename.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`export::check_pdf_options` refuses what `pdf_report` would: the export
options, the flattener, and now `pageLayout` and `view`, which `pdf_report`
reads up front too. `file.package` checks with it before the output folder
is made, so an unknown page layout or view leaves no partial package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`findFormat.chars` must be an object and `charStyle` / `paraStyle` style
names (or null); any other value is an error instead of being skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/compose/src/tests.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
`style.paragraph.create` and `style.character.create` refuse a `basedOn` or
`nextStyle` that is neither a style name nor null, instead of dropping it and
creating the style without the reference, as `style.paragraph.edit` does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
Keep In Frame holds a rule above inside the frame (its top), not below the
top inset. A rule's gap colour in Text Color (`Text Color` or
`$ID/Text Color`) imports as Text Color, as the rule's colour already did,
and exports as a string property rather than as no swatch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
The Line tool keeps the line it previews (in spread space, Shift and
snapping included) for the readout, instead of measuring from the press to
the pointer in canvas coordinates. Nothing shows before the first drag step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
#	crates/tools/src/select.rs
# Conflicts:
#	ROADMAP.md
#	crates/tools/src/select.rs
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	ROADMAP.md
#	docs/target-app-parity.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
`object.textWrap`'s `offset` takes null for a side to keep each object's own
offset there. Unlinked, Properties sends only the edited side, so with
several objects selected each keeps its other three offsets. The link's
state is kept per selection: another selection whose four offsets are the
same starts linked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
`object.textWrap` takes `mode: null` for each object's own mode. Properties
sends it with an offset or Invert edit, so objects with another wrap mode
than the first keep theirs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
As in InDesign, Preferences with no document open has Units & Increments:
the horizontal and vertical ruler units, the ruler origin and the cursor-key
and kerning increments. They are kept with the application preferences
(`prefs.set {defaultUnits}`) and new documents start with them; New Document
opens in those units, and its [Default] card uses them. A document keeps its
own Units & Increments once made, and Preferences with a document open still
edits that document's.

`file.new` without a preset or `units` uses the default units; units picked
in New Document set both rulers unless they are the default horizontal ones,
which keep the default vertical units.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
An index past the last page was clamped to the end; now it is refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The command takes `on` (default: toggle), and Preferences OK runs it with the
chosen state instead of setting the flag itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shift pressed on a selected anchor point keeps it selected, so the press can
become a constrained drag of all the selected points; a Shift-click still
takes it away, on release. With Shift, a snap moves the points only along
the constrained direction. The canvas looks selected points up in a set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
#	crates/tools/src/tests.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`path.moveAnchors` points may carry their own spread-space movement
(`[id, subpath, index, dx, dy]`). Dragging and the arrow keys send each
selected point's movement converted for its spread, so on a spread turned on
screen a point moves the way the pointer or arrow does. Delete and Backspace
with points selected run `path.deletePoints`. Properties › Transform for
selected points shows the points' bounds; X/Y move them and W/H spread or
gather them about the reference point, in one step (`transform_anchors`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`after` or `before` past the last page is refused without overflowing and
changes nothing; inserting after the last page still appends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While the press is still a click (inside the drag tolerance), a drag event
moves nothing, so the release takes the point away without moving it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A document made from a preset keeps the preset's units on both rulers; the
default origin and increments still apply. Preferences with no document open
passes the increments it reads to `prefs.set` unclamped: a Cursor Key of 0,
or text that isn't a measure or number, is refused and the dialog stays open
with the reason; a Kerning/Tracking of 0.5 is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
French and Italian text is hyphenated with hyph-utf8's patterns, through
hypher's "french" and "italian" features (hyph-fr.tex 2.13, MIT; hyph-it.tex
4.9, LPPL or MIT, taken under MIT; NOTICE has both). The Character panel's
French, French: Canadian, French: Swiss and Italian, and fr / it locale codes,
select them.

A word with an elision hyphenates after its apostrophe (l'im-pri-me-rie,
dell'im-pa-gi-na-zio-ne) in the patterned languages; before, any word with an
apostrophe was left whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	crates/ui-egui/src/i18n.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	crates/ui-egui/src/i18n/fr.rs
Units & Increments for new documents go in the same prefs.set as the rest,
which checks everything before it changes anything, so a refused increment
keeps the dialog open with no preference saved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
Paragraph Style Options › Paragraph Shading and Paragraph Border are headed
with the page's name; Tint is a spinner with InDesign's presets and has
Overprint beside it (shading, border stroke and gap: new paragraph
attributes, read and written in IDML as ParagraphShadingOverprint,
ParagraphBorderOverprint and ParagraphBorderGapOverprint; PDF export warns
that it doesn't overprint yet, as for objects). Corner Size and Shape is
InDesign's two-by-two grid of corner icons, size spinners and shape menus
showing each shape's glyph, with the link in the middle; the offsets have
spinners, with the edges and width beside them; the weights have spinners.

Found in the Learn Skills Daily course, chapter 41.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both change the Direct Selection tool: #902's corner pull now builds the
anchor drag with this branch's list of other selected anchors (none), so the
two build together; both sets of tests are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As InDesign: a selected anchor shows both its direction handles, and its
neighbours the handle that shapes the segment to it; with no anchor
selected no handle shows. Handles that don't show can't be grabbed (one
rule, select::handle_shown, for drawing and hit testing). The pen and the
anchor tools still show every handle. Under the anchor tools the selection
is drawn as its path and points, without the bounding box.

Found in the Learn Skills Daily course, chapter 43.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A single selected point has no size, so Transform's W and H read 0p0. InDesign
shows the object's width and height there, greyed out and not editable; with two
or more points they measure (and set) the points' bounds as before.

SelInfo keeps the selected objects' size from before the points replace the
bounds, and the anchor Transform section shows it in disabled W/H fields when
one point is selected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
- selection.toggle dropping an item from the selection now drops its selected
  points too. They stayed in selection.anchors, so the arrow keys still moved
  points of a frame that was no longer selected.
- path.appendAnchor at the start moves the sub-path's selected points up one
  place, as path.reverse remaps them, so they keep naming the same anchors.

Found by CodeRabbit on #1657.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
The Delete key already ran path.deletePoints under Direct Selection, but
Edit › Clear (the menu item, a native accelerator, or the control channel)
called edit.clear, which removed every path whose points were selected. With
points selected and no ids given, edit.clear now deletes those points, as
InDesign's Clear does.

Found by CodeRabbit on #1657.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
path.appendAnchor read `subpath` with as_u64, so -1 or "0" counted as omitted
and the point went onto the last subpath. Only an omitted (or null) subpath
means the last one now; any other value must be a valid index.

Found by CodeRabbit on #1657.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As in InDesign (Learn Skills Daily / Adobe "How to make a table" lesson):
- With the Type tool in a table cell, Shift+Tab goes to the previous cell.
  It went on to the next one: the tool sent a plain Tab whatever the
  modifiers.
- Esc in a cell toggles between the text and the cell: the insertion point
  or text in a cell selects that cell, and selected cells select the text of
  the first one. Esc left the table and selected the frame.

New engine command table.toggleSelection does the toggle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Table menu: Insert Table… (Cmd+Alt+Shift+T), Convert Text to Table,
  Convert Table to Text | Cell Options | Insert, Delete, Select | Merge,
  Unmerge, Split Horizontally/Vertically, Convert Cell Type, Convert Rows |
  Distribute Rows Evenly, Distribute Columns Evenly. The Table panel item left
  the menu (it is in Window › Type & Tables, Shift+F9).
- Cmd+Alt+Shift+T opens the Insert Table dialog, as InDesign's; it ran
  table.insert with its defaults, so the shortcut and the menu did different
  things.
- The Insert Table dialog: InDesign's title, a narrow window, Body Rows and
  Columns then Header and Footer Rows as numbers with spinners and
  right-aligned labels, and a Table Style applied to the new table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Table › Convert Text to Table… and Convert Table to Text… open dialogs laid
out as InDesign's instead of converting at once with tabs and paragraphs:
- Column and Row Separator: Tab, Comma, Paragraph from the field's menu, or
  any characters typed.
- Number of Columns (Convert Text to Table), available when both separators
  are the same: the cells fill rows of that many.
- Table Style (Convert Text to Table), applied to the new table in the same
  undo step.

table.convertFromText takes rowSeparator, columns and tableStyle, and any
characters as separators; table.convertToText takes both separators
(Table::text_with). Convert Text to Table is available only with text
selected outside a table, as in InDesign. New strings are translated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every text cell now shows its own hidden characters: spaces, tabs, paragraph
returns and an end-of-story # after its text (an empty cell shows just the #).
The table paragraph's return sits after the table's bottom right corner.
Cells showed no marks at all, so an empty table looked like plain lines.

The table marks come from table_hidden_marks (frame space), drawn with the
story's own marks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
selection.cells may start at a covered grid position; the toggle now goes to
the merged cell (its owner at the top left), whose story holds the text.
Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
- table.insert takes tableStyle and applies it in its own edit, so one Insert
  Table is one undo, and a style that is gone (or not a name) changes nothing.
  The dialog passes it instead of running style.table.apply afterwards.
- The dialog's fields stop at table.insert's limits (500 body rows, 200
  columns, 100 header or footer rows; now public constants), so the table made
  is the one shown.

Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/dialogs.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
- A table's glyph-less line drew its own end mark at the table's bottom right,
  sized to the table's height, under the new one: table lines now have no
  line marks (the drawn ¶ is the table paragraph's).
- Marks come from frame_hidden_marks, which visits a cell's own tables, so
  nested tables' cells are marked too.

Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
path.moveAnchors treated a non-list points as absent and fell back to the
id/anchors form, so a request with a malformed points and an id moved that
path. Found by CodeRabbit on #1657.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	crates/engine/src/cmd/object.rs
# Conflicts:
#	crates/engine/src/tests.rs
# Conflicts:
#	crates/idml/src/tests.rs
A cell selected with Esc (or a drag inside it) kept the caret at the start of
its text, so typing went in front. With one cell (or one merged cell)
selected, text.insert now selects the cell's whole text first, as InDesign
replaces the contents. Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As the other dialogs do (Cell Options, Text Frame Options): on an error the
message goes to the status bar and the dialog comes back with what was typed.
Found by CodeRabbit on #1679.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An emptied separator field reached table.convertFromText / convertToText,
which refuse it; the dialog closed and lost what was typed. On an error the
message goes to the status bar and the dialog comes back, as the other
dialogs do (Insert Table included, from #1676). Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	crates/engine/src/tests.rs
# Conflicts:
#	docs/target-app-parity.md
# Conflicts:
#	docs/target-app-parity.md
# Conflicts:
#	crates/geom/src/units.rs
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/tests.rs
# Conflicts:
#	crates/engine/src/cmd/find.rs
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/tests.rs
#	crates/ui-egui/src/dialogs.rs
# Conflicts:
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	crates/engine/src/cmd/layout.rs
# Conflicts:
#	crates/engine/src/cmd/find.rs
# Conflicts:
#	crates/engine/src/cmd/find.rs
# Conflicts:
#	crates/tools/src/text.rs
# Conflicts:
#	crates/engine/src/cmd/edit.rs
#	crates/engine/src/tests.rs
#	crates/tools/src/select.rs
Main's insert_pages_bounds.rs and a_page_count_insert_pages_cannot_mean_is_refused
pin that an `after` past the last page appends. This branch had made it an error;
`before` (new here) still has to name a page, and both together are refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
#	crates/compose/src/parabox.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The catalogue test refuses a key in both fr.rs and the shared table (CI).
The shared row keeps the French; it matches, or takes fr.rs's text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The catalogue test refuses a key in both fr.rs and the shared table (CI).
The shared row keeps the French; it matches, or takes fr.rs's text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dialog::s turned JSON null into the string "null", which table.insert refused
as an unknown style. The field is read as text, and null or empty means
[Basic Table]. Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merges #1676 (a null table style is no style), and:
- The dialog compares separators as table.convertFromText resolves them, so
  "comma" and a typed "," are the same and Number of Columns applies.
- The column count goes to the engine as given: 0 is refused (the dialog stays
  open) instead of becoming 1.
- At most 200 columns, table.insert's MAX_COLUMNS, in the engine and the field.
- The help says the words tab, comma and paragraph name those separators.
- A short last row's padding cells take the text's paragraph and character
  format (Table::from_strings formats every cell).

Found by CodeRabbit and @skylartaylor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A style the font lacks counts as a missing font in Summary and Fonts, as
  file.package counts it (font_status).
- The dialog remembers its document; Package... and Continue refuse when another
  document became active meanwhile, so the package is the one summarised.
- Enter in Address or Instructions makes a new line: the dialog footer no
  longer takes it for Continue (dialogs::MULTILINE_FOCUS).
- Instructions.txt starts with the printing instructions, then the report, as
  the dialog promises.

Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/package_dialog.rs
- A GREP match that is empty (^) was counted but got no paragraph style; the
  paragraph style now goes to the paragraphs of every match, empty ones too.
  Character formatting still needs characters.
- apply_char_style and apply_para_style listed every paragraph of the story
  for each match; Story::paras_touching gives the ones a range reaches, from
  the range itself.

Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Screen readers got only the swatch name; the painted marks (colour type and
mode, can't be edited) were not in it. The row is now named "Cyan, Process,
CMYK" or "[Black], Process, CMYK, Cannot be edited" (translated; one new
string). Tests find rows by name with names_swatch. Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
#	crates/ui-egui/src/icons.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
#	docs/target-app-parity.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
#	docs/target-app-parity.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/widgets.rs
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	docs/ui-parity.md
# Conflicts:
#	ROADMAP.md
#	docs/ui-parity.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
# Conflicts:
#	ROADMAP.md
#	docs/typography-parity.md
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/file.rs
{"offset": [null, null, null, null]} parsed as an offset edit, so the custom
wrap boundary (from IDML) was dropped although no side changed. An array with
no number in it is no offset edit. Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merge of main kept both the branch's and main's accessibility call, so a
click emitted two Clicked events. Main's (with the enabled state) stays.
Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ROADMAP.md
# Conflicts:
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	crates/ui-egui/src/lib.rs
# Conflicts:
#	crates/ui-egui/src/canvas.rs
# Conflicts:
#	crates/compose/src/grep.rs
# Conflicts:
#	docs/target-app-parity.md
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/style.rs
#	crates/engine/src/cmd/text.rs
#	crates/ui-egui/src/dialogs.rs
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/style.rs
#	crates/ui-egui/src/dialogs.rs
# Conflicts:
#	crates/engine/src/cmd/object.rs
#	crates/ui-egui/src/dialogs.rs
#	docs/target-app-parity.md
# Conflicts:
#	crates/ui-egui/src/effects_dialog.rs
# Conflicts:
#	crates/engine/src/cmd/export.rs
#	crates/engine/src/cmd/package.rs
#	crates/ui-egui/src/lib.rs
A row wider than MAX_COLUMNS, or more cells than the largest table
table.insert makes (MAX_BODY_ROWS x MAX_COLUMNS), is an error before
the table is built; the text stays as it was.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
So the command refuses it (and the dialog stays open) instead of the
table being made unstyled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
So the command refuses it (and the dialog stays open) instead of the
table being made unstyled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As Insert Table's: the command refuses it, and the dialog stays open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The caret in a footnote has a CellAddr too (FOOTNOTE_TABLE). Shift+Tab
and Esc there now act as outside a table, and table.nextCell,
table.prevCell and table.toggleSelection refuse it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The picker has no backdrop, so a page can lie under it; color_at only
checks the canvas. The drop now samples only when the picker's layer
isn't the topmost one there, and the test drops onto its colour field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The panel keeps the uid of the document it last showed; another one
(switched to, or moved into its place by a close) drops the rename and
the pending rename click, so a same-named swatch there isn't renamed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dialog shows the first selected object's corners and sent all
four, so other objects lost corners nobody touched. object.cornerOptions
now takes null for a corner (each object keeps its own), and the dialog
sends only the corners edited: changed from the first object's, or set
by a linked edit (all four).

A shape the dialog doesn't offer is an error that keeps it open,
instead of another shape taking its place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
egui activates a focused button with Enter, and the footer, drawn
after it, took the same Enter for OK: the dialog closed and made the
table of contents. The toggle now consumes that Enter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
main moved to egui 0.37 (#1810) and named the old picker's fields. The
picker's own layout here takes the new API (Role for WidgetType,
scope_id, Id::unique, TextEdit::align) and names its value fields by
their captions and the hex field "Hex".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
# Conflicts:
#	crates/ui-egui/src/widgets.rs
At 100% K a device CMYK conversion is black whatever C, M and Y are,
so the picked RGB stayed the same and the `p != before` guard dropped
the typed percentages. They are stored (and the colour marked edited)
whenever a C/M/Y/K field was typed in; the rest still only when the
colour changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Typing in C switches the picker to CMYK, which the swatch test's OK at
the end then applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found while testing crates/epub/src/css.rs:~128-153 (the character-style loop in stylesheet_with)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The canvas fix moves to canvas/frames.rs and its test to canvas/tests.rs; the variables test
lines to cmd/variables/tests.rs, with upstream's splits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
The IDML import and export of edited cross-reference text move to import/story.rs and
export/story.rs with upstream's split.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
Keeps story_para under clippy's cognitive-complexity limit, which upstream now enforces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
decode_rgba relied on the image crate's 512 MiB limit, which bounds
only the decoder's own output. A gray or 1-bit image just under it
expanded four times to RGBA, and render made a premultiplied copy on
top: a 288 KB PNG of 23,000 x 23,000 pixels froze the first draw for
9 s and took the app to 4.5 GB. The size is now read from the header
and anything past 256 Mpx is refused before decoding. It draws as an
empty frame, and PDF export skips it with a warning.

A 300 ppi scan of an A0 sheet (about 139 Mpx) still opens.
With compressImages on, PDF export re-encodes rasters as JPEG in
recompress, which decoded with the image crate directly. A gray PNG
that decode_rgba refuses still decoded there, was copied and encoded
as JPEG, and only then dropped: krilla refuses a JPEG wider or taller
than 16,384 px, and every raster past the budget is. Exporting the
23,000 px PNG that way took 4.2 s and 1 GB more memory, for a PDF
without the image.

recompress now asks too_large_to_decode first, the check decode_rgba
uses, so the export skips the image with the same warning at once.
The test for a raster past the RGBA budget showed that recompress
skips the decode only through a one-second limit, which a slow CI
runner could fail and a fast machine could pass without the fix.
recompress now counts its decodes in a test-only per-thread counter,
and a unit test checks that the 16,385 px PNG doesn't reach the
decode while a 9 px one does. The export test keeps its output
checks and drops the time limit.
# Conflicts:
#	crates/ui-egui/src/canvas.rs
# Conflicts:
#	crates/engine/src/cmd/table.rs
#	crates/engine/src/cmd/text.rs
# Conflicts:
#	crates/tools/src/select.rs
#	crates/ui-egui/src/canvas.rs
# Conflicts:
#	crates/engine/src/cmd/file.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
# Conflicts:
#	crates/engine/src/cmd/layout.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
#	crates/ui-egui/src/panels/pages.rs
# Conflicts:
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/chrome.rs
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/ui-egui/src/panels/swatches.rs
# Conflicts:
#	crates/ui-egui/src/panels/swatches.rs
# Conflicts:
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	docs/target-app-parity.md
# Conflicts:
#	crates/doc/src/item.rs
#	crates/idml/src/export.rs
#	crates/idml/src/import.rs
#	crates/ui-egui/src/effects_dialog.rs
# Conflicts:
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	crates/tools/src/select.rs
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/properties.rs
#	docs/target-app-parity.md
# Conflicts:
#	crates/ui-egui/src/canvas.rs
# Conflicts:
#	crates/tools/src/select.rs
#	crates/ui-egui/src/canvas.rs
# Conflicts:
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/engine/src/cmd/file.rs
#	crates/tools/src/snap.rs
#	crates/ui-egui/src/canvas.rs
# Conflicts:
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/ui-egui/src/panels/pages.rs
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
# Conflicts:
#	crates/engine/src/cmd/style.rs
#	crates/idml/src/export.rs
#	crates/idml/src/import.rs
#	crates/ui-egui/src/dialogs.rs
# Conflicts:
#	crates/idml/src/import.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
# Conflicts:
#	crates/ui-egui/src/new_document.rs
# Conflicts:
#	crates/doc/src/attrs.rs
#	crates/format/src/lib.rs
# Conflicts:
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/swatches.rs
# Conflicts:
#	crates/tools/src/select.rs
# Conflicts:
#	crates/tools/src/select.rs
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
# Conflicts:
#	crates/ui-egui/src/panels/pages.rs
# Conflicts:
#	crates/engine/src/cmd/table.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	crates/doc/src/table.rs
#	crates/engine/src/cmd/table.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	ROADMAP.md
#	crates/doc/src/attrs.rs
#	crates/idml/src/export.rs
#	crates/idml/src/import.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/engine/src/cmd/style.rs
#	crates/engine/src/cmd/text.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
# Conflicts:
#	crates/engine/src/cmd/style.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/ui-egui/src/panels/properties.rs
# Conflicts:
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/swatches.rs
#	docs/target-app-parity.md
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
# Conflicts:
#	crates/engine/src/cmd/find.rs
#	crates/engine/src/cmd/style.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/icons.rs
# Conflicts:
#	crates/engine/src/cmd/find.rs
#	crates/engine/src/cmd/style.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/icons.rs
# Conflicts:
#	crates/engine/src/cmd/find.rs
#	crates/engine/src/cmd/style.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/icons.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	crates/compose/src/lib.rs
#	crates/doc/src/attrs.rs
#	crates/idml/src/export.rs
#	crates/idml/src/import.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
# Conflicts:
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	crates/engine/src/cmd/package.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
# Conflicts:
#	crates/engine/src/cmd/export.rs
#	crates/engine/src/cmd/package.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Footnote text is addressed as a cell too (as 2e44b190 handled for
Shift+Tab, Esc and the cell commands); text.insert now types the Tab
there instead of failing in table.nextCell.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps the function within clippy's cognitive complexity limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps color_picker within clippy's cognitive complexity limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps color_picker within clippy's cognitive complexity limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tone() decoded a GIF to RGBA and decode_cmyk_tiff() called read_image()
without the header check decode_rgba() runs. Both now call
too_large_to_decode() first. The decoders' own limits (image 512 MiB,
tiff 256 MiB) already refused these files; the guard refuses them from
the header instead.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps document_sections within clippy's cognitive complexity limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Matches InDesign/Photoshop: plain click keeps the shown tool; Alt-click advances the slot without opening the menu.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
egui pairs a plain click with a prior Alt-click as a double-click; remember the previous click's Alt so polygon/transform dialogs only open for two plain clicks.
Prefer the primary-release event's modifiers for Alt-cycle, and suppress polygon/transform dialogs when either click of a double was modified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps para_box_attrs within clippy's cognitive complexity limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CodeRabbit nitpick: after the last group tool, the next Alt-click must return to the first and keep the flyout closed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ignore primary releases outside this tool button so another widget cannot steer Alt-cycle or suppress dialogs; harden the Alt-click test to clear i.modifiers before release.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
egui still counts a click when the pointer leaves the tool rect; keep the release modifiers when the press started on the slot. The Alt-cycle test now uses 1 ms frames so an Alt-then-plain pair is a real double-click that must not open Polygon Settings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A click with a frame tool opened the Rectangle dialog in picas whatever
Preferences > Units & Increments or the rulers' unit menus said. It now
shows the width in the horizontal ruler unit and the height in the
vertical one, and reads bare numbers typed in each field the same way.
The properties panel and the control channel open it the same way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa

# Conflicts:
#	ROADMAP.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa

# Conflicts:
#	ROADMAP.md
The running-header placeholder on parent pages moves to its own branch
(running-header-placeholder), as asked in review, so each lands on its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
On a parent page a running-header variable shows <Name>, as InDesign shows it (it was blank). Text
with no page that isn't on a parent (a frame composition can't place on a page) keeps the
variable's text before and after: frames now record whether they are on a parent spread, and
the composed values are cached by page and parent.

Split from #1232 (parent-page-display), as asked in review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
An imported cross-reference's text is regenerated only when it is exactly what its format
generates for its destination (Document::drop_generated_xref_text, once the destinations are
resolved); "Page 7, revised" is an edit and is kept, as is the text of one whose destination is
gone. The loose in-order match (matches_format) is gone. Page numbers are recognised by the
instance's AssociatedTextVariable (a cross-reference page number variable, or InDesign's name
for it when the file doesn't define it) rather than its Name, and text inside tracked-change
wrappers counts as shown (insertions in, deletions out). Export writes generated text with its
page numbers as the live variable too, so it reads back as generated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
A test for all eleven ruler units (points to Ha): the width and height
the dialog shows read back as the frame's size, so OK never resizes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dialog kept its width unit from when it opened but read the height
in the vertical ruler unit of the moment, so rulers switched while it
was open (the control channel's document.preferences) turned a typed
50 mm into 50 in. It now keeps the vertical unit too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The picker sits over the page's middle on main's dialog layout, and a
drop on the picker takes nothing, as it should.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The picker's modal backdrop covers the screen on main, so no point is
outside its host layer; the drop check compares with the picker's own
layer, which the middle of the frame isn't on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts:
crates/ui-egui/src/panels/properties/object.rs: kept both: #1420's text_frames argument in swatch_menu calls and #1499's double-click Color Picker blocks
crates/ui-egui/src/dialogs/tests.rs: kept both sides' appended tests
Conflicts:
crates/ui-egui/src/panels/properties/object.rs: kept both new functions (open_color_picker from #1499, opacity_slider from #1389)
crates/ui-egui/src/dialogs/tests.rs: kept both sides' appended tests
crates/ui-egui/src/i18n/*.rs (table, ar, cs, it, ka, pl, pt_br, ru, uk): kept both sides' rows (unique keys)
crates/engine/src/tests.rs: kept both new tests (#902 corner pull, #1125 image delete)
Conflicts:
crates/ui-egui/src/panels/properties/tests.rs: kept both new tests (#1389 opacity slider, #1394 frame fitting)
Conflicts:
crates/ui-egui/src/panels/properties/tests.rs: kept both sides' tests (earlier merged tests plus #1390's text wrap offsets test)
On main the dialog is a modal whose transparent backdrop shares the
picker's layer and covers the screen, so comparing layers took every
drop for one on the picker and the eyedropper took nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts:
crates/ui-egui/src/panels/properties/tests.rs: kept both sides' tests (earlier merged tests plus #1414's two tests)
crates/ui-egui/src/dialogs/tests.rs: kept both sides (the new character-style test added next to #1464's)
crates/ui-egui/src/i18n/*.rs: kept #1464's rows and added only #1492's new keys (New Paragraph/Character Style); older copies of #1464 rows dropped
Conflicts:
crates/ui-egui/src/panels/properties.rs: combined the two cfg(test) object imports (preview_row from #1414, align_to_icon from #1437)
Conflicts:
crates/ui-egui/src/i18n/*.rs (table, ar, cs, de, it, ja, ka, pl, pt_br, ru, uk): kept both sides' keys (#1414's Stroke Type/Corner Shape, #1406's Corner Size and Shape:), no duplicates
crates/ui-egui/src/dialogs/tests.rs: kept HEAD, appended #1496's new test
crates/ui-egui/src/i18n/*.rs: kept both sides' rows (unique keys)
Conflicts:
crates/ui-egui/src/i18n/*.rs (table, ar, cs, de, it, ja, pl, pt_br, ru, uk): kept both sides' keys (#1406 and #1414 corner keys, #1413 Join/Convert Point/Plain/Symmetrical), no duplicates
Conflicts:
crates/ui-egui/src/dialogs/tests.rs: kept both tests (#1406 corner options, #893 new section)
crates/ui-egui/src/i18n/*.rs (ar, cs, de, it, ja, ka, pl, pt_br, ru, uk): kept both sides' keys, plus #893's New Section
crates/ui-egui/src/dialogs/tests.rs: kept HEAD, appended #1512's new test
crates/ui-egui/src/i18n/*.rs: kept both sides' rows (unique keys)
Conflicts:
crates/ui-egui/src/menus/tables.rs: kept the Fitting separator from the Object menu order (#1413); #1433's own comment line dropped
crates/ui-egui/src/i18n/*.rs (ar, cs, de, it, ja, ka, pl, pt_br, ru, uk): kept both sides' keys, plus #1433's Clear Frame Fitting Options
crates/ui-egui/src/dialogs/tests.rs: kept HEAD, appended #1554's new test
crates/ui-egui/src/dialogs/tests.rs: kept HEAD, appended #1513's new test
crates/ui-egui/src/i18n/*.rs: kept both sides' rows (unique keys)
crates/ui-egui/src/dialogs/tests.rs: kept HEAD, appended #1286's new test
crates/ui-egui/src/dialogs.rs: TOC title row by hand: the reserved-width title field (#1285) with its accessible name, and the style selector keeping the label-id name argument
crates/ui-egui/src/dialogs/tests.rs: kept HEAD, applied #1285's 450->360 viewport edits in 3 tests, appended its new test
crates/ui-egui/src/dialogs/tests.rs: kept HEAD, appended #1257's new test
Keeps color_picker within clippy's cognitive complexity limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts: dialogs/tests.rs and i18n/{ar,cs,it,ka,pl,pt_br,ru,uk}.rs: adjacent additions from both sides, both kept.
Conflicts: engine/src/tests.rs and i18n/*.rs: adjacent additions from both sides, both kept.
# Conflicts:
#	crates/compose/src/tests.rs
# Conflicts:
#	crates/compose/Cargo.toml
#	crates/compose/src/hyphen.rs
#	docs/gaps.md
#	docs/localization-parity.md
#	docs/typography-parity.md
# Conflicts:
#	crates/render/src/fx.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found while testing crates/doc/src/xref.rs:85-91 (expand)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Integrate 43 reviewed PRs
crates/engine/src/tests.rs: kept main's tests and the PR's new tests
crates/tools/src/tests.rs: kept main's tests and the PR's new tests
crates/ui-egui/src/panels/swatches.rs: kept main's row marks and color_target_or_defaults, added the in-place rename field before them; tests find rows by names_swatch (main's longer accessible names); chapter 23 doc comment moved onto the main test.
crates/tools/src/select.rs: dropped the doubled corner-pull block (the PR's copy of the old code and main's); kept one with main's content-mode fix and the stack's others field
crates/engine/src/tests.rs: kept main's tests and the PR's new test
crates/ui-egui/src/canvas/frames.rs: kept the PR's handle_shown filter
Applied as the diff of #1496 (already in main) to #1497's head; the old copy of #1496 (story.rs paras_touching, paragraph.rs ranges) is not taken.
crates/engine/src/cmd/find.rs: main's tests kept, paragraph style outside the non-empty check as in main
crates/ui-egui/src/i18n/*.rs: union of keys
docs/target-app-parity.md: main's text plus the Find Format wording
crates/tools/src/select.rs: took the PR's later anchor_selection and moved_points use; kept main's content-mode-off corner pull
crates/ui-egui/src/canvas/frames.rs: kept the handle_shown filter from #1657
crates/ui-egui/src/panels/properties.rs: kept main's imports
crates/ui-egui/src/panels/properties/tests.rs: kept both sides' tests
crates/ui-egui/src/i18n/{ar,cs,de,it,ja,ka,pl,pt_br,ru,uk}.rs: union of both sides' keys
Applied as the diff of #1497 to #1498's head; the older copy of #1496 is not taken.
crates/engine/src/cmd/find.rs: PR's found-text Change path; format_only keeps main's cleared-attributes case
crates/ui-egui/src/dialogs/tests.rs: main's tests kept, the PR's Change test added
crates/ui-egui/src/i18n/*.rs: union of keys
docs/target-app-parity.md: main's text plus the Change wording
crates/ui-egui/src/effects_dialog.rs: kept both the angle dial tests (main) and the blend mode test (PR); the stray 'The dialog's body.' doc line moved back onto show.
crates/ui-egui/src/dialogs.rs: both dialog tests kept
crates/ui-egui/src/i18n/*.rs: union of keys
docs/target-app-parity.md: main's change line plus the Text Frame Options entry
crates/ui-egui/src/panels/properties.rs, properties/object.rs: main's split module kept; preview_row and paint_corner_shape exported for the shading corner menus
crates/ui-egui/src/panels/properties/tests.rs: both sides' tests kept
crates/ui-egui/src/dialogs/tests.rs: main's tests kept; the border test uses the new corner labels; the shading layout test added
crates/ui-egui/src/i18n/*.rs: union of keys without duplicates
crates/ui-egui/src/dialogs.rs: the corner shape face uses corner_shape_button (no hard-coded colour in the dialog)
crates/ui-egui/src/dialogs/tests.rs: kept main's create-guides test and the PR's colour picker test
crates/ui-egui/src/panels/pages.rs: kept #1287's marker activation and tests; spread label code from #892 (main).
The swatch outline reads Tokens::field_border. The field cross, the slider markers and the
OK pill's white text stay fixed colours: they sit on arbitrary colours or on the accent fill,
as in the other dialogs' OK buttons.
crates/engine/src/cmd/table.rs: kept both exports.
crates/engine/src/cmd/table/structure.rs: main's strict size validation with #1676's limit constants and table style.
crates/ui-egui/src/dialogs.rs: kept Insert Pages dialog and #1676's Insert Table dialog; dialog title and width from #1676.
crates/ui-egui/src/dialogs/tests.rs: kept both sides' tests.
The colour picker draws its own buttons, so the generic footer's Enter/Esc handling does not run for it. It now consumes the keys it handles and lets a button click win over a key in the same frame.
The merge of PR #1503 took main's and #1080's merged picker as is; this applies the eyedropper's own delta on top of upr/1080 (canvas::color_at, drag-from-picker in dialogs.rs, tests, picker strings). Conflicts: dialogs.rs kept the single-fire Enter/Esc handling with the eyedropper's trimmed OK key; the i18n tables keep both sides' entries.
crates/engine/src/cmd/table.rs: both export lists.
crates/engine/src/cmd/table/structure.rs: #1676's Insert Table validation, #1679's MAX_CONVERTED_CELLS.
crates/ui-egui/src/dialogs.rs, dialogs/tests.rs: kept #1676's Insert Table dialog, Insert Pages and #1679's Convert dialogs and tests.
crates/ui-egui/src/menus/tables.rs, tests.rs, ui_commands.rs: flat Convert Cell items; Convert dialogs in the menu.
crates/ui-egui/src/i18n/*.rs: kept both sides' keys.
crates/idml/src/import.rs, tests.rs: conflicts were the old pre-split copy; PR's three small changes ported by hand into import/document.rs, names.rs and tests.rs
crates/idml/src/tests.rs: kept the PR's TOC tests, dropped the duplicate copy from #1249
crates/engine/src/tests/idml.rs: main's createBookmarks plus the PR's right-indent separator
crates/ui-egui/src/dialogs.rs: main's labelled_by fields plus the PR's special-character menu
crates/ui-egui/src/i18n/*.rs: kept both added rows
crates/ui-egui/src/dialogs.rs: kept main's Insert Pages dialog and the PR's MULTILINE_FOCUS key
crates/ui-egui/src/i18n/*.rs: kept both sides' rows
Status and warning colours come from the theme's warn and error colours instead of hard-coded RGB values.
The Summary lines use neutral wording of our own (keeping the feature names); i18n keys and the test follow, translations carry over.
Enter in a multi-line field is a new line only in the Printing Instructions dialog; the flag now uses a stable id (Id::unique never matched) and is cleared for every dialog.
crates/ui-egui/src/dialogs.rs: kept the Enter-stays-local fix
crates/ui-egui/src/package_dialog.rs: kept the summary wording and the fix; took the PR's pdf option value
crates/ui-egui/src/i18n/*.rs: kept the reworded keys and the PR's PDF Preset rows
Also (the PR's own CI failure): package.rs calls check_pdf_options and pdf_report on wasm, so those two re-exports are no longer wasm-gated (only pdf_export is).
Found while testing crates/engine/src/cmd/xml.rs:~215-245 (parse: the Start/Text/End depth handling; text at depth >= 4 matches no arm)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Conflicts: panels/properties.rs imports (union); i18n/*.rs adjacent rows (both kept).
Conflicts: dialogs/tests.rs and i18n/*.rs: adjacent additions, both kept.
Conflicts: i18n/*.rs adjacent rows (both kept).
Conflicts: dialogs.rs dialog widths (both kept); i18n/*.rs adjacent rows (both kept).
* fix(flatpak): allow reading launcher version pins

* fix(flatpak): allow reading launcher version pins
Three files conflicted. In dialogs.rs both sides added code after doc_unit: the
PR's doc_vertical_unit and frame_size_dialog stay, followed by main's reworded
Create Guides doc comment. In dialogs/tests.rs both sides appended tests at the
end of the file: all of main's tests stay and the PR's two Rectangle dialog
tests follow them. In panels/properties/object.rs main now opens Corner Options
from the Properties Corner link, so main's line is kept and the PR's change there
(the Rectangle dialog through frame_size_dialog) is dropped, since that link no
longer opens the Rectangle dialog.

Follow-up beyond the conflicts: main added a Dialog struct literal for the
Change Format dialog, which now also sets the PR's new vertical_unit field to
None so the crate builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main refuses a size outside the limits instead of clamping it, so the test inserts the largest table and checks one step over each limit is refused.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Integrate 21 held PRs (rebase and fixes)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Separate the CJK commands from Insert Math Expression in the Type menu (#2043)
Add File > Quit to the in-window menu on Windows and Linux (#2044)
Spellcheck squiggles follow the text frame rotation (#2042)
macOS: Finder opens .indd and .indt files with DesignCraft
Parents: single-sided pages in a spread show the parent page in their place
Skip quoted attribute values when finding the end of an xref tag
Keep text of nested inline elements in file.importXml
Images: refuse a raster that would decode past 1 GiB of RGBA (fixes #1586)
Keep underline, strikethrough, caps and tracking in EPUB/HTML character styles and overrides
Toolbar: Alt/Option-click cycles the flyout tool group
# Conflicts:
#	crates/ui-egui/src/dialogs/tests.rs
# Conflicts:
#	crates/doc/src/xref.rs
# Conflicts:
#	crates/ui-egui/src/dialogs/tests.rs
Rectangle dialog: width and height in the ruler units, not always picas (#1964)
Parent pages: document-page overlays no longer pile onto the parent canvas
Parent pages: running headers show their name on the parent itself only
Cross-references keep edited text and break at spaces
Import warnings: Show selects the frame a story warning is about
Updates: shared check-result dialog from craft-update
Merge pull request #2070 from aiongg/docs-tidy
Some checks failed
ci.yml / Merge pull request #2070 from aiongg/docs-tidy (pull_request) Failing after 0s
nix.yml / Merge pull request #2070 from aiongg/docs-tidy (pull_request) Failing after 0s
packaging-lint.yml / Merge pull request #2070 from aiongg/docs-tidy (pull_request) Failing after 0s
sonarcloud.yml / Merge pull request #2070 from aiongg/docs-tidy (pull_request) Failing after 0s
ci.yml / Merge pull request #2070 from aiongg/docs-tidy (push) Failing after 0s
nix.yml / Merge pull request #2070 from aiongg/docs-tidy (push) Failing after 0s
packaging-lint.yml / Merge pull request #2070 from aiongg/docs-tidy (push) Failing after 0s
sonarcloud.yml / Merge pull request #2070 from aiongg/docs-tidy (push) Failing after 0s
ea214dd44d
docs: tidy agent, contributor and asset docs
alf merged commit ea214dd44d into main 2026-10-31 16:53:02 +00:00
alf deleted branch chore/sync-upstream-20261031 2026-10-31 16:53:02 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
iris/designcraft!15
No description provided.