Four holes CodeRabbit found on 648dd428:
- alignment_frame framed a one-row paragraph when any alignment entry
was set, including one past the draft's rows, and then moved rows
with no alignment of their own to the column's edge. It now takes the
draft and frames only when every draft row is aligned, by its own
alignment or the paragraph's.
- remap could not tell which of two same paragraphs an edit took
("A\nA" to "A"), and kept the deleted one's alignment. remap_at takes
the caret where the edit ended, and the typing path (follow_typing,
both editors) passes it from the box's state. The caret only chooses
between readings that fit both texts.
- Both editors judged a focus loss by where a click landed, so focusing
a Format text control by keyboard or a screen reader (no pointer)
closed the box before the alignment was chosen. They now also judge
by where the keyboard went (focus_pos): focus outside the document
view, or on the added-text box's own buttons, keeps the box open as a
click there does.
Each change has a test seen failing before it.
Two holes in alignment_frame:
- A column's right edge came from the runs that start at its left
edge, so a row of several styles ended at its first run, and the
column could fail to hold a title wider than that run. It now takes
the right edge of each complete row (row_rect).
- A row with no column to align in was framed by its own box, which
the rewrite also used as the width its text wraps at: changing an
isolated row's text together with an alignment wrapped it at its old
width, word by word. When the text changes and no column holds the
row, alignment_frame now returns None, so the row keeps the width it
has without the alignment. With the text unchanged the own box is
still the frame, so aligning twice is still a no-op.
alignment_frame measured a one-row paragraph's alignment in the frame
of the nearest overlapping block. A full-width heading closer to the
title than the title's own body column gave it a page-wide frame, so
centring or right-aligning the title moved it out of its column. It now
considers every overlapping block whose column holds the row and takes
the narrowest, the nearest on a tie, so a page-wide heading gives the
title no frame while a narrower column that holds it does. When no
column holds the row it is still measured in its own box.
The comment about page-wide headers named an exclusion the filter
never made; the doc comment now says what is chosen and why.
Main split and refactored the text-rewrite code this PR changes
(automation dispatch.rs, edit added/ and text/, text_regions/styled.rs).
Conflicts in added/store.rs, text/rewrite.rs and text_regions/styled.rs
take main's structure, with per-row alignment applied in it:
- rewrite.rs: LineWriter keeps the paragraph's alignment and the rows'
own (align, aligns); each line looks up its row's alignment
(align_of) for justify and for its offset. Alignment::offset takes the
row's alignment. Wrapped lines carry their row, as wrap returns it.
- styled.rs: wrap_styled_rows also returns each row's draft line
(row_lines), which the kept-rows check counts aligns by.
- Imports for the moved modules (alignment_frame, BlockStyle,
align_code, align_from, content in dispatch.rs).
craft-libs#366 drops the default-features override on craft-keymap that
older Cargo rejects. FreeBSD aarch64 builds with Rust 1.98.1 and failed
with "no matching package named craft-menu found" (craft-libs#364).
* Refactor annot for strict Clippy checks
* Refactor automation for strict Clippy checks
* Refactor cos for strict Clippy checks
* Refactor edit for strict Clippy checks
* Refactor engine for strict Clippy checks
* Refactor export for strict Clippy checks
* Refactor forms for strict Clippy checks
* Refactor js for strict Clippy checks
* Refactor organize for strict Clippy checks
* Refactor pdfcraft-cli for strict Clippy checks
* Refactor preflight for strict Clippy checks
* Refactor print for strict Clippy checks
* Refactor redact for strict Clippy checks
* Refactor render for strict Clippy checks
* Refactor sign for strict Clippy checks
* Refactor ui canvas for strict Clippy checks
* Refactor ui commands for strict Clippy checks
* Refactor ui dialogs for strict Clippy checks
* Refactor ui support for strict Clippy checks
* Refactor ui tools for strict Clippy checks
* Refactor ui workflows for strict Clippy checks
* Refactor xfa for strict Clippy checks
* Refactor xfdf for strict Clippy checks
* Enforce workspace Clippy standards and document lint policy
* Fix menu overflow and form pointer handling
* Group annotation, form and document operation parameters
* Group signing and timestamp validation inputs
* Group demo form field properties
* Group UI interaction and rendering parameters
* Restore translated security and shortcut labels
* Fix platform-gated imports for Windows and wasm builds
* Qualify signing calls for macOS and Windows builds
* Restore the preflight check flow and the overflow menu title
The pre-signing check matched any folder named Program Files, so it rejected
a valid MSI when Windows resolves Program Files elsewhere, accepted the 64-bit
root for an x86 package and accepted a different app name. Build the expected
folder from the package architecture's resolved root and the policy name.
Export > Image spent its time in the PNG, JPEG and TIFF encoders, one
page after another: on a 55-page manual at 150 dpi, drawing every page
took about 0.34 s and encoding it 1.1 s (PNG) to 2.0 s (JPEG).
Exporter::images exports a list of pages, drawing and encoding several
at once on worker threads, each with its own PageRenderer (as
automation's extract_parallel does), and hands the files to a sink in
page order on the calling thread. Workers draw at most one page ahead
of the sink and fewer run when 1 GiB can't hold that many of the
largest page. The first page or sink error stops the export with every
earlier page handed over, as before. A page panic becomes that page's
error, and a panicking sink stops the workers. One page, one core or
wasm keeps the per-page loop. Export > Image and the doc_export_images
tool use it.
Files are byte-identical. One core is left for the interface (at most
8 workers). With examples/export_bench, on a Ryzen with 16 threads
(shared), mean of two medians of 21 runs:
PNG 150 dpi 1874 -> 340 ms (-82%)
JPEG 150 dpi 2106 -> 340 ms (-84%)
TIFF 150 dpi 2032 -> 375 ms (-82%)
PNG 300 dpi 3804 -> 590 ms (-84%)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Real msiexec runs (per-user and all-users, silent and wizard) found two defects
that the metadata fixtures cannot see:
- "Only for me" published ALLUSERS=2, so FindRelatedProducts treated the run as
per-machine and skipped the existing per-user copy. An interactive upgrade
left two registered products and uninstall left files behind. The page now
leaves ALLUSERS unset for a per-user choice.
- Windows Installer resolves Program Files once, for the context it started in,
so choosing "Everyone" in the wizard installed into the user profile with a
machine-wide registration. The wizard now sets the new-install folder itself
after the choice (Program Files, Program Files (x86) for 32-bit, or the
per-user Programs folder). Silent installs are unchanged.
check-install-policy.ps1 now fails if either regresses.