Found while testing crates/textimport/src/docx.rs:354
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ST_OnOff (ECMA-376 17.17.4) is a boolean plus the words on and off, but
the toggle reader only counted 0/false/none as off — so <w:b w:val="off"/>
(a legal spelling written by non-Word producers) imported as bold, and
the same for <w:i>, <w:strike>, <w:caps>, <w:isLgl> and <w:u>.
Add "off" to both off-lists. Regression test:
off_valued_toggles_stay_off — on main the off run imports bold; with the
patch it stays regular and an on run stays bold.
Composite-font and mojikumi metrics were taken from the file with no
sanity check, and Document::check rejects a zero, NaN or infinite
relative_size / horizontal_scale / vertical_scale / baseline_shift — so
one attribute anywhere in the package (RelativeSize="0",
BaselineShift="NaN") failed the import with "invalid composite font
metrics" and left the file unopenable. Every neighbouring number in this
importer already filters; the metrics now do too and fall back to a
usable value.
Regression test: unusable_cjk_metrics_do_not_refuse_the_whole_file —
fails on main with Invalid("invalid composite font metrics: Rubies"),
passes with the fallback.
The "N errors ▾" text in the status bar was a plain label. As in
InDesign it is now a menu; its Preflight Panel… entry shows the panel
(`window.panel {panel: "preflight"}`).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 533ba782643314e5841fb8bb58cd3af4bf2dd9ae)
Moving, resizing and drawing snapped to page edges, margins, columns and
ruler guides but never to the bleed guide. `Spread::bleed_rect` now holds
the bleed rectangle (shared by the canvas, which drew it with its own
copy of the rule), and the guide pass offers its four sides.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit ad7a78d7439a906ab3545ff98801ee37b15be127)
With frame edges shown, every text frame that ends an overset story
carries the red mark at its out port, selected or not and inside
groups too. InDesign marks only the selected frame, so an overflowing
label inside a grouped object stayed invisible until Preflight.
Hidden frames and hidden layers are skipped; the group walk is bounded.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit d9ef96dd4b8189b423b4fc32bbb4bf6e3c5c6727)
(cherry picked from commit b60500660ba1dd02bd5c09dd35e0e3238b6ae21b)
A selected group drew no in/out ports for the text frames in it, so an
overset frame inside a group had no red mark. The selection walks groups
(bounded depth) and draws each nested text frame's ports with the group's
transform.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 17a3cf9bd1c695a585e94fce125ed9d3a3a5929d)
German terminology made consistent and easier to understand: Anschnitt for
bleed (Beschnitt already meant crop), Vorlagenseite for parent pages,
Intelligente Hilfslinien/Maße/Abstände, 90° nach rechts/links instead of the
UZS abbreviation, Anzahl der Ecken, Zielmedium, PDF mit Tags, Aufgabenleiste,
Position for the gradient stop location.
45 interface strings had no German row and fell back to English (23 of them
added to the shared table after the German table: Data Merge, PowerPoint
export, composite fonts, odd/even page breaks, ...); all now have one.
Preferences > Guides & Pasteboard (Align to Object Edges/Centers, Smart
Dimensions/Spacing, Snap to Zone) and Insert Cross-Reference > Link To drew
their labels without tr, so they stayed English in every language.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A package opened away from its author's machine kept image links like
`/images/logo.png` that no longer exist; only the package folder and its
Links/ folder were searched, so images in `images/` next to the .idml
showed as missing. Also try the link's trailing folders (up to 8) under
the package folder, longest first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only these two dialogs read bare numbers in the ruler unit; other dialogs keep their meaning.
Apply to: this page, both pages of the spread, or all pages. Parent edits default to the whole parent spread.
Replace unchecked indexing in inherited_guides and marginsAndColumns with get().
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRYQ5eieuUrtxhdbh6goq
Dragging a variable font axis slider previews the change on the page and
commits it as one undo step when the slider is let go. The panel gathers what
every axis slider did in a frame before acting, so with several axes a drag no
longer commits and reopens the change on every frame. A click, an arrow key or
a value typed in the field beside each slider applies at once. Narrow axes
(Skia's weight runs 0.48-3.2) step by hundredths; a slider snapping a value
that is off its steps no longer counts as a change.
Live previews are commands, so the panel stays on app.run: edit.preview
{label, command, params} shows an edit on the document as it was before the
preview began, edit.commitPreview makes it one undo step, edit.cancelPreview
drops it. A preview no panel held in the last frame (its slider let go, or the
panel closed) is committed at the start of the next one.
The Character panel drops its repeated heading, lays Size, Kerning and
Baseline, and Leading and Tracking, out in two columns whose captions and
fields line up, shows auto leading in parentheses, and shows a style with
axis settings as its axes alone, here and in the Text Frame floating bar.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep GuideType=Liquid on document and parent pages, with literal XML and
mixed-guide regression coverage. Leave object liquid constraints separate.
Co-Authored-By: Codex <codex@openai.com>
The height search stopped up to 0.011 pt short of it (a line is set within 0.01 pt), so a fitted
frame scaled up with its text came out overset. InDesign fits 70 pt Kanji_PA to 18.521 mm, its
ascent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In InDesign, holding Cmd (Ctrl) with the Type or a drawing tool makes a
press select, move or resize as the Selection tool would, without
switching tools; the Pen family gets Direct Selection. The engine now
borrows that tool from a Cmd-held press to the release, keeps the chosen
tool, and shows the borrowed tool's cursor while Cmd is held.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011K1peyrh5MdZ6ttHkVq8Gh
The DOCX and IDML element-tree builders accepted any depth, and the
tree is then walked and dropped recursively; a DTD content model's
groups recursed without a budget. Each parser now refuses nesting past
a fixed budget with an error, before any recursive consumer runs.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011K1peyrh5MdZ6ttHkVq8Gh
Double-clicking selected a word, but holding the button and moving did
nothing. `text.extendTo` now takes `unit`: after a `text.selectAt`, the
selection grows by whole units from the unit first selected, in either
direction, as InDesign does. The Type tool sends the unit its clicks
chose with every drag.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011K1peyrh5MdZ6ttHkVq8Gh
Conflicts:
- crates/doc/src/build.rs: kept parent_page_of/parent_page/parent_guides,
sync_parent_margins and mark_differing_margins_local; inherited_guides(abs)
stays as a wrapper over parent_guides for the guide commands and dialogs.
Kept main's single_sided_page_shows_first_parent_page test next to
differing_margins_from_older_files_stay_local.
- crates/doc/src/page.rs (auto-merged): Spread::parent_page_index takes main's
rule (first parent page for left and single-sided pages).
- crates/engine/src/cmd/layout.rs: the parent block uses sync_parent_margins
instead of main's old-margins equality check; parent accepts prefix, label or
index; document pages set here become local. Main's
parent_margins_change_the_parent_and_follow_unoverridden_pages stays; added
applying_a_parent_gives_its_margins_and_local_margins_stay_local.
- crates/tools/src/snap.rs, crates/ui-egui/src/canvas.rs: guides read through
parent_guides (no per-page Vec); main's current_spread_page and
current_parent_page kept.
- crates/ui-egui/src/panels/properties.rs: main's parent-target margin fields.
- crates/format/src/lib.rs: upgrade and merge_duplicate_assets, then
mark_differing_margins_local.
- crates/engine/src/tests_idml.rs: both sides' tests.
- ROADMAP.md: main's file plus this PR's progress-log line.
Conflicts and how each was resolved:
- crates/idml/src/import.rs: main's linked_assets and insert_asset kept; the
crop is read beside main's page (PDFAttribute as a child or a property), and
linked_assets is keyed by (path, page, PdfCrop) so two crops of one page are
two assets.
- crates/idml/src/export.rs: PDFAttribute with PageNumber, PDFCrop and
TransparentBackground is written for every placed PDF, replacing main's
page > 0 block.
- crates/idml/src/tests.rs: main's file plus the `$ID/` font tests.
- crates/engine/src/cmd/file.rs: main's exact PDF page size, place cursor and
add_asset kept; Crop to stores the choice on the asset (the graphic spans
the box), so the place cursor's frame crop box is gone.
- crates/engine/src/cmd/{book,interchange}.rs: main's confined and reporting
imports, with the PDF crops resolved after them.
- crates/engine/src/cmd/print.rs: main's print_with, exporting with the
measured PDF boxes.
- crates/engine/src/cmd/links.rs: main's text links plus pdfCrop.
- crates/engine/src/cmd/{datamerge/fill,mathexpr,media,table}.rs,
crates/format/src/lib.rs: main's add_asset with the asset defaults.
- crates/engine/src/cmd/package.rs, crates/engine/src/tests_idml.rs: both
sides' tests.
- crates/fonts/src/fontdb.rs: main's style traits, looked up through
plain_family.
- crates/render/src/lib.rs: pdf_crop_box replaces pdf_page_box; main's
UserUnit test checks pdf_crop_box.
- crates/ui-egui/src/dialogs.rs: main's dialog with the content-bounds crops.
Also: Asset::same_file compares the PDF crop, so placing or saving no longer
merges two crops of one page; Asset literals added on main take the defaults;
main's PageNumber test checks the crop and that page 1 is written; new tests
a_pdf_page_placed_with_two_crops_imports_as_two_assets and
pdf_assets_with_different_crops_stay_apart.
#84 landed on main squashed (0f4f382b0), so the merge was resolved against #84's
tip as the base: main's version of #84 stands and only this branch's IME changes
are applied on top.
Conflicts and how each was resolved:
- crates/engine/src/cmd/text.rs: removed main's text.compose command, compose_text
and its compose_tests; text.insert keeps main's reset of the typing format after a
successful edit, skipped while an IME preview is open; reselection bumps the
revision.
- crates/engine/src/lib.rs: removed Session.composition and the hook that ended it
in execute_unguarded; set_active/add_document end the composition and reset the
Find scope; both test modules kept.
- crates/engine/src/tooling.rs: removed main's composition() and its
end_composition (the opposite semantics); begin_interaction no longer ends a
composition.
- crates/engine/src/cmd/edit.rs, file.rs, guard.rs, recovery.rs: main's code with
bump_revision in place of revision arithmetic; Revert takes the fresh state's
revision.
- crates/ui-egui/src/canvas.rs: removed main's IME block, composition highlight and
remembered caret rect; this branch's ime_event/ime_output stay. Main's dead-key
test is ported to these events (the accent stays as typed when the caret moves).
- crates/ui-egui/src/lib.rs, menus.rs: both sides' fields and checks.
- apps/designcraft/src/main.rs, apps/designcraft-web/src/web.rs: both sides.
- docs/control-protocol.md: ui.ime row plus main's ui.click/ui.drag params.
Also: the remaining `revision += 1` sites on main use bump_revision, and two tests
compare revisions with `>`; the IME candidate window follows the caret on type on a
path; IME status lines in ROADMAP.md, gaps, ui-, localization- and target-app-parity
docs and roadmap.md.
Conflicts:
- crates/compose/src/lib.rs: kept main's line placement (line_metrics with first
baseline tops, baseline grid snap) and this branch's leading model and Aki Below
advance. The Hyphenation Zone check uses Composer::single_line(), so the Japanese
single-line composer gets the zone too.
- crates/idml/src/tests.rs: kept both tests at the conflict (composer kinds, text
stroke alignment).
Also resolved:
- crates/idml/src/import.rs: removed the package scan for a Japanese composer and the
drop of [No paragraph style]'s leading model; the import keeps the file's leading
model and the composer kind, and compose applies the model per paragraph.
- crates/idml/src/tests.rs: the default-leading-model test lays out the document and
checks Roman spacing under the non-Japanese composers and the Aki Below spacing
under the Japanese ones; a new test round-trips a Japanese composer document.
The Typography panel's Other Features section lists the otf::TOGGLES tags no other section shows. Choosing a figure style or width alone also sets the other axis (the one all of the selection has, else Proportional or Lining), so IDML export writes a figure style instead of Default; turning one off clears both axes. Standard Ligatures reads and sets the ligatures attribute through type.char, and type.openTypeFeatures reports liga from it.