chore: sync upstream (129 Commits) #10

Merged
alf merged 129 commits from chore/sync-upstream-20261024 into main 2026-10-24 09:49:17 +00:00
Owner

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

  • c313c534 refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728)
  • 4c5ea73d refactor(tools): fewer parameters and simpler pointer handling (Sonar S107, S3776) (#1725)
  • 75d5b015 refactor(idml): extract helpers to cut cognitive complexity (Sonar S3776) (#1723)
  • cb763c25 refactor: split complex functions in psd, table, parabox, index, trace, pdf export, render (Sonar S3776) (#1724)
  • 8271f1a2 refactor(engine): split execute_unguarded, load_styles and resize_border (Sonar S3776) (#1726)
  • c142678b refactor(ui-egui): extract character style General section (Sonar S3776) (#1720)
  • e0c244d2 refactor(ui-egui): extract style option field helpers (Sonar S3776) (#1719)
  • e651c637 refactor(ui): extract helpers from conditions, book, credits and page control panels (Sonar S3776) (#1721)
  • 8299d264 chore: replace trivial closures with method paths (Sonar S1612) (#1714)
  • bfd95b25 chore: drop redundant 'static lifetimes in statics and consts (Sonar S8863) (#1713)
  • f90d2867 chore: resolve SonarCloud maintainability issues (#1698)
  • 5449bc47 M6: preserve PDF catalogs and safely apply layer choices (#1670)
  • 00d5fa5c M6: reject unreadable PDF trailer history links (#1670)
  • 7427a158 M6: harden placed PDF layer variants (#1670)
  • d8d78851 Anchored objects: Relative to Spine mirrors custom positions on right-hand pages (#1702)
Upstream-Sync von `upstream/main` (129 Commits). Fast-Forward. - c313c534 refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728) - 4c5ea73d refactor(tools): fewer parameters and simpler pointer handling (Sonar S107, S3776) (#1725) - 75d5b015 refactor(idml): extract helpers to cut cognitive complexity (Sonar S3776) (#1723) - cb763c25 refactor: split complex functions in psd, table, parabox, index, trace, pdf export, render (Sonar S3776) (#1724) - 8271f1a2 refactor(engine): split execute_unguarded, load_styles and resize_border (Sonar S3776) (#1726) - c142678b refactor(ui-egui): extract character style General section (Sonar S3776) (#1720) - e0c244d2 refactor(ui-egui): extract style option field helpers (Sonar S3776) (#1719) - e651c637 refactor(ui): extract helpers from conditions, book, credits and page control panels (Sonar S3776) (#1721) - 8299d264 chore: replace trivial closures with method paths (Sonar S1612) (#1714) - bfd95b25 chore: drop redundant 'static lifetimes in statics and consts (Sonar S8863) (#1713) - f90d2867 chore: resolve SonarCloud maintainability issues (#1698) - 5449bc47 M6: preserve PDF catalogs and safely apply layer choices (#1670) - 00d5fa5c M6: reject unreadable PDF trailer history links (#1670) - 7427a158 M6: harden placed PDF layer variants (#1670) - d8d78851 Anchored objects: Relative to Spine mirrors custom positions on right-hand pages (#1702)
alf added 129 commits 2026-10-24 09:49:16 +00:00
Found while testing crates/color/src/ase.rs:131-132

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/docx.rs:183-185

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/docx.rs:134-135

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/geom/src/units.rs:276

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/engine/src/cmd/object.rs:710-711 (also :975)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
`Fallback::begin` returns before the fallback runs when `WGPU_BACKEND`
is set, logging that wgpu picks the backend. So the line below it is
reached only when the variable is *not* set -- and it said
"(WGPU_BACKEND overrides)", which reads in a log as though the user's
environment had chosen the backend when nothing had.

    before: graphics: DirectX 12 (WGPU_BACKEND overrides)
    after:  graphics: DirectX 12 (first choice; set WGPU_BACKEND to choose another)

The report quotes that line as evidence of which backend a start used,
which is exactly the wrong conclusion to be led to.

Part of #1343.
Found while testing crates/engine/src/cmd/table.rs:1396-1403

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Fixes #1337

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Fixes #1340

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Two corrections to the message, both reported by CodeRabbit on #1371.

switched_from being None only means this start did not switch from a
backend that never showed a frame. A backend that failed on an earlier
start is remembered in the record, and choose() then picks the first
candidate that is not in that list -- so calling it the "first choice"
misstates how it was arrived at. The line now says either "nothing has
failed before" or which backends had, so the log says what happened.

The comment claimed that reaching this line means WGPU_BACKEND is
unset. wgpu-types returns an empty mask for an empty or unrecognised
value and begin() only returns early for a non-empty one, so such a
value reaches here with the variable set. The comment says that instead.
Found while testing crates/textimport/src/rtf.rs:237

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/tagged.rs:35 (also :52)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- English (and Auto where offered) stays first as the source language and fallback; the rest sort by native name with accents folded, so Čeština is under C and Magyar under M; Cyrillic and CJK names follow the Latin ones
- The list used the registry order, which is the order the languages were added
A tab draws nothing, so it was left out of the underline and strikethrough
bars: they stopped at the last letter before each tab and began again after it.
Forms rule their fill-in lines with underlined tabs — `Name ⇥⇥⇥⇥, city ⇥⇥⇥⇥` —
so an imported form lost every writing line, and an IDML `Underline="true"` on
a run of tabs drew nothing at all.

A tab is a character with an advance, and InDesign rules its whole width.
`PlacedGlyph::spans_rules` says which glyphs a rule runs across: the drawn
ones, and a tab or a right-indent tab that advances. The spaces a line break
trimmed off the end, the break characters and the markers' carriers are not
part of the line's text and are still skipped, so an underline stops at the
text and not at the frame edge.

Both places that draw the bars from the glyphs use it: the renderer
(`build_line`) and the PDF export (`text_rules`). The HTML and PPTX exports
mark up runs of text, which already included their tabs.

Measured on the repro in the issue, a 420×120 pt page at 2×:

  before   one underline, 63 px: the word "Name"
  now      three, 63 + 219 + 231 px: the word and both tab stretches

and the exported PDF gains the two fills for them. A tab with a leader is one
continuous bar across the leader dots to the right-aligned text after it.

Tests: the renderer's bars and the PDF export's bars for "Name<tab>City" are
one bar covering the tab's width, not two with a gap where it is. Both fail
without the change (two bars, 36→67.7 and 72→93.2, the tab's 67.7–72 unruled).
A gradient made in the Gradient panel stayed unnamed: there was no way
to drag it into the Swatches panel for reuse. The panel's thumbnail now
drags the selection's gradient, and the Swatches list takes the drop as
a new gradient swatch (swatch.new, "New Gradient Swatch"). A gradient
that already is a swatch is left as it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found while testing crates/idml/src/names.rs:148-155

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/engine/src/cmd/object.rs:2519

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A cell's text rotation (Cell Options › Text › Rotation) was already read from
IDML and written back, but only 0 is composed, so an imported form's narrow
header columns of vertical labels came in horizontal and wrapped mid-word
("Eingela / ngt am") — and nothing anywhere said why. The reporter's file has
30 such cells.

Composing rotated cell text is a larger change than this. What this does is
stop it being silent, and let the value be set from the API:

- the IDML import reports it once per file: "2 table cell(s) have rotated text
  (Cell Options › Text › Rotation): the angle is kept and written back, but the
  text is composed horizontally";
- `table.setCell` takes `rotation` (0, 90, 180 or 270, any other angle refused,
  negatives and multiples normalised), which nothing could set before;
- `table.get` reports each cell's rotation, so a round trip can be checked.

Tests: the angle through an export and back with the warning counted once for
the file (and no warning when no cell is rotated), and the command's accepted
and refused angles. Each fails without its own part.
The same selection written two ways gave different files:

    file.exportPdf {"pages": "2,2"}   → 1 page
    file.exportPdf {"pages": [2, 2]}  → 2 pages, the second a copy
    file.exportPdf {"pages": [2,2,2]} → 3 pages

`parse_page_range` keeps the first of a repeat (`"2-2,2"` is one page too); the
array form appended whatever it was given. A list says which pages to export,
not how many times, so the array now drops a repeat as the string does. Both
`file.exportPdf` and `file.exportPptx` read the same parameter.

The test pins the agreement between the two forms over nine lists, in PDF and
PPTX, and the two facts I measured while checking it: the pages come out in the
document's order whichever order the list names them in, and `[2, 2]` is now
byte for byte the file `"2"` gives. A page that does not exist is still
refused, and an empty list still exports nothing.

Not from a ticket: I found it probing the page-range parameter.
Found probing `layout.pages.insert` on a two-page document:

    {"count": 0}      → one page inserted  (0 clamped up to 1)
    {"count": -1}     → one page           (`as_u64` fails, the default applies)
    {"count": 1.5}    → one page           (the same way)
    {"count": 10000}  → 9999 pages, quietly capped

A count that is given is a number of pages, so each of those is a usage error
now: "count 0: 1 to 9999 pages". A count that is absent still means one page.

`after` is left alone. My first attempt also refused a position past the last
page, and `insert_after_u64_max_appends_at_the_end` caught it: appending is
what an out-of-range `after` is meant to do, and the test now says so in the
same place.

The test covers the five counts, that none of them inserted anything, that a
position past the end still appends, and that `{"count": 2, "after": 0}` still
inserts two pages after the first. Without the check, `{"count": 0}` inserts a
page again.

Not from a ticket: I found it probing the command's parameters.
`anchor.create` took any name, including one another anchor already had, so a
document could hold two anchors called "Photo 1". Every reference to the name
then means whichever the search finds first: `xref.insert {"anchor": "Photo 1"}`
and `hyperlink.create {"anchor": "Photo 1"}` take the first, and an export
writes both destinations under the one name. A name nobody can resolve is not a
name.

A name already in the document is a usage error now, naming it and where to
look: "a text anchor named `Photo 1` is already in this document (anchor.list
names them)". A name that is empty or only spaces is refused too — a
cross-reference built from `<txtAnchrName />` would show nothing.

Case still distinguishes names, as it does elsewhere in the document, and
nothing about existing anchors changes: the check is on creation.

The test covers the same name in the same story and in another one, the empty
names, that only one anchor exists afterwards, and that another name and a
name differing in case are both fine. Without the check the duplicate is
created again.

Not from a ticket: found probing `anchor.create`.
Nothing checked type size. `type.char {"size": 0}` set type with no size at
all, a negative size went in the same way, and 1e9 pt asked the composer for a
line a million times the height of the page — all of it silent, and all of it
saved to the document.

The range is the one this engine already applies to a ruby annotation's size,
0.1 to 1296 pt, which is InDesign's: "size 0: 0.1 to 1296 pt".

It sits in `validate_char_fill`'s place in the chain, so every command that
takes character attributes gets it: `type.char`, `find.change`, the four
`style.character` / `style.paragraph` create and edit commands, and the two
table paths that already validated a fill.

The test covers five refused sizes, the three in range including both ends, and
two of the style commands. Without the check, `{"size": 0}` applies again.

Not from a ticket: found probing `type.char`.
Track text state through graphics saves and drawn forms; exempt invisible text. Report font names and pages in export warnings and validation without embedding or outlining placed fonts.
The drop zone held the ungrouped swatches only, so releasing the
gradient over a colour group's row did nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first-line indent was added to the left indent whatever the paragraph's
direction, so a right-to-left paragraph's first line moved the wrong way. With
the hanging indent a numbered list uses — right indent 10 mm, first line
−10 mm — the first line went 10 mm outside the frame on the left while the
wrapped lines sat where it should have been.

It is the paragraph's start-side indent, which is the right one in a
right-to-left paragraph; the drop-cap case beside it already made that
distinction.

Measured on a 200 pt column with that hanging indent:

  first line    right edge 200     (the frame's edge, as InDesign sets it)
  wrapped       right edge 171.65  (10 mm in)
  every line    left edge >= 0     (nothing outside the frame)

and the same paragraph left to right is unchanged, first line at 0 and wrapped
lines 10 mm in.

The test checks both directions; the right-to-left half fails without the
change. 359 composition tests pass unchanged.
The start screen's community card reserves the button's measured width, so
the line beside it wraps before the button. Georgian's label overflowed the
fixed 190 px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
Found while testing crates/textimport/src/rtf.rs:197-243 (the \u handler at :235-242; control words never decrement `pending`)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/lib.rs:117

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Autoflow (Shift-click, autoflow on Place, text.thread with autoflow) inserted
new pages right after the story's last frame, in front of the document's own
pages. As in InDesign, it now threads one frame per column on each page that
follows, whatever else the page holds, and only then adds pages at the end of
the document. It fills whole pages, so an estimate that stops inside a page
can't leave its later columns out of the thread. Frames it set past the end
of the text are removed again; the pages they were on stay. Smart Text Reflow
of the primary text frame keeps adding pages after the story's last page.

Shrinks gap 26: flowing into the primary text frame of the following pages
is left.
The Help menu's links were greyed out when no document was open, because UI commands outside app. and window. needed a document. The test checks every help.* UI command is enabled with an empty session while another UI command (view.rulers) stays disabled. Without the help. exemption it fails on "help.discord must work from the start screen".
The start screen showed only the first ten presets and had no A6 sheet. The test checks that the start screen paints a card for each print preset, that A6 exists at 105 x 148 mm, and that the Properties page-size list agrees. Without the fix it fails because the B5 card is cut off by take(10) and there is no A6.
A menu row only reacted over its text because the column used a plain top-down layout. The test renders a menu column with a short Preferences row and clicks near the right end of the row, expecting the dialog to open. Without the justified layout the click misses and the test fails.
Fixes #1474

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #1589

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A string without a translation shows in English, and an empty catalog row
counts as untranslated. Tests keep duplicate-key and placeholder checks and
the lookup, context, plural-caption and right-to-left mechanics; coverage,
stale-key, wording and per-language literal checks are removed.

`cargo xtask i18n-report`, also a `cargo xtask ci` step, runs the ignored
missing_translations_report test and prints the missing strings per language.
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>
Autoflow: fill the pages that follow before adding pages at the end
Fix slice panics in the PDF post-passes on malformed page trees and metadata (#1591)
Align towards/away from spine on parent-page folios by page side (#1577)
IDML export: write the graphic placed in a table cell (#1551)
Cursors: paint the tool cursors in the window on Wayland, so they keep the system size (#1544)
Decode UTF-16 plain text files by BOM on import
ui: the Discord button widens to fit its label instead of spilling out
Skip control words and symbols used as RTF \uN fallbacks
Drop out-of-range RTF \uN values instead of wrapping them
A type size outside 0.1 to 1296 pt is refused
Save and export dialogs start in the document's folder, or the last one used (#1653)
# Conflicts:
#	crates/idml/src/tests.rs
Keep non-finite IDML numbers out of imported documents
Reload ICC profiles loaded in Color Settings at start-up
Make the start screen scrollable on short windows (#1655)
find: search and change text inside table cells in document scope (#1624)
idml: explicit zero cell edge weights hide the default table border (#1623)
Align: a click on one of several selected objects makes it the key object
# Conflicts:
#	crates/ui-egui/src/menus.rs
Regression tests for #248, #249 and #329
Clamp polygon side count before narrowing to u32
Fix "-0p0" for tiny negative pica/cicero values
Remember the Preview checkbox in Paragraph/Character Style Options
Graphics: the start-up log says which backend was chosen and how to change it
Refuse PDF page ranges in the Place PDF dialog instead of using page 1
Saturate table alternating-fill and index paragraph counts
Keep ':', '<', '>' and '\' in Tagged Text style names
A text anchor's name is the document's, so it is not reused
A page named twice in an export list is exported once
Gradient panel: drag the gradient onto the Swatches panel to keep it
A page count Insert Pages cannot mean is refused
# Conflicts:
#	crates/compose/src/tests.rs
A right-to-left paragraph's first-line indent is at its right edge (#1448)
# Conflicts:
#	crates/idml/src/tests.rs
Rotated cell text is settable and reported, not silently flattened (#1468)
Clamp text frame column count before narrowing to u32
# Conflicts:
#	crates/idml/src/tests.rs
Keep a literal ':' in style names through an IDML round trip
An underline runs across a tab, as the rest of the line's text (#1466)
Preferences: list the languages alphabetically by their own name
Export placed greyscale TIFFs as DeviceGray
Keep CDATA text in the DOCX/XLSX XML parser
Drop out-of-range font sizes on DOCX import
Truncate ASE swatch names that overflow the u16 length field
# Conflicts:
#	docs/gaps.md
#	docs/target-app-parity.md
PDF: report visible unembedded fonts in PDF/X-4
* fonts: Georgian UI text from craft-fonts' Noto Sans Georgian

font_definitions registers the Geor face and appends it to every family, like
Arabic (and to the Arabic families after the CJK faces); the wasm filter in
crates/fonts/build.rs keeps the face. The installed-font probe for Geor stays
skipped whenever craft-fonts covers the script. Bump craft-fonts-ref to a71c20e
(storytold/craft-fonts#27).

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

* Release: build the web version with craft-fonts too (web-craft-fonts)

The shared release workflow builds the web release without CRAFT_FONTS_DIR unless web-craft-fonts
is set, so the web version would still have no Georgian face (CodeRabbit on vectorcraft#2934).

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

* test: the Arabic New Document test scrolls to Height like the other fields

With craft-fonts' Noto Sans Arabic (from a71c20e3) the rows above Height are taller, so at
392x271 the field starts partly below the dialog body's clip and the test's unscrolled
visible_label check failed (FreeBSD jobs). It stays reachable: scroll to it as the test
already does for Gutter and the margins.

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

* CI: same craft-fonts pin as release (a71c20e3), so the gate checks the Georgian face

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Links: use resolve_absolute for stored paths

* Links: check for a missing linked file with is_ok_and

* CI: release only with git dependencies from storytold

The winit patch from skylartaylor/winit at its pinned rev is the one other source allowed.

* Links: Relink to Folder only uses a name that stays a file name in the folder

* CI: the git-sources check reads Cargo.lock as TOML, needs it current and refuses config patches

* CI: the git-sources check parses .cargo/config and .cargo/config.toml for source replacement, patches and paths

* Links: rustfmt

* Links: Relink to Folder only takes a file directly in the chosen folder

* Links: Relink to Folder compares folders as the file system resolves them
* PDF: craft-pdf, krilla and hayro from craft-libs main (input bounds and crash fixes)

* PDF: craft-libs 9f75d3dc, with hayro-cmap from its vendored copy
* Anchored objects: Relative to Spine mirrors custom positions on right-hand pages

* Anchored objects: page side from the frame's spread position; footnote cache keyed by page side
Integrate current main (d8d78851) without rewriting the contributor's commits, retaining craft-libs 9f75d3dc.

Accept literal null trailer entries while rejecting actual or ambiguous encryption/hybrid markers. Structurally inspect bounded xref/trailer history instead of adopting trailer-looking comments. Preflight all selected source variants before editing/undo; preserve reset-to-defaults. Suppress stale unrewritable canvas overrides rather than revealing source content. Keep conservative all-content crop fallback without overcropping layerless/null stubs.

Validation: cargo xtask ci, all 9 gates passed; 3062 tests passed, 6 skipped; all 16 WASM-safe crates checked. 17 supported variants passed independent qpdf, logical preservation and Poppler pixel checks; 6 unsupported/repair-only cases refused. Direct-harness Claude Opus 5 reviewed the exact main-relative delta with no blocking findings.

No native-format changes or unrelated layer features. Synthetic regression fixtures are generated in test code.
Reject a non-null Prev entry that cannot be read as an offset instead of silently treating it as the end of the guarded trailer chain. Keep absent/null end markers and readable numeric offsets unchanged.

Reproduced CodeRabbit discussion_r4366245854 with an independent probe and a failing native regression before the fix. The synthetic regression covers seven unreadable value types plus absent/null and integer/real history controls.

Validation: all 9 cargo xtask ci gates passed (3063 tests passed, 6 skipped; 16 WASM-safe crates). One unrelated GPU test was labelled leaky by nextest in that run and passed cleanly in an isolated rerun. Independent checks: 17 original supported PDF variants still pass qpdf, logical preservation and Poppler pixels; 6 original refusal cases remain refused. All 11 additional Prev controls pass (7 refused, 4 accepted).
Preserve existing PDF catalog entries and full object generations. Accept literal null trailer entries while failing closed on encrypted/hybrid/ambiguous or unreadable history. Validate visibility variants atomically before document edits, suppress stale unsupported canvas overrides, and preserve conservative content cropping without overcropping empty optional-content stubs.

Local full CI: all 9 gates passed, 3063 tests passed and 6 skipped, all 16 WASM-safe crates checked. Independent qpdf/preservation/Poppler checks passed for17 supported inputs;6 refusal cases stayed refused. All11 additional Prev controls passed. GitHub CI and CodeRabbit passed on00d5fa5c; CodeRabbit confirmed the Prev finding addressed. Author history preserved; no native format changes.
* chore: resolve SonarCloud maintainability issues

- Replace lambda closures with method references (S1612)
- Replace wildcard imports with explicit imports (S2208)
- Refactor complex functions with extracted helpers (S3776)
- Replace OR pattern with range pattern in math parser (S9047)

* style: apply rustfmt to warichu helper

* fix(compose): revert slice conversion in tests and remove unused var in warichu

* Group warichu row layout scalars to satisfy S107 parameter limit

* style: satisfy rustfmt in warichu.rs

---------

Co-authored-by: Dylan Taylor <dylan@craftmaker.dev>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728)
Some checks failed
ci.yml / refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728) (pull_request) Failing after 0s
nix.yml / refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728) (pull_request) Failing after 0s
packaging-lint.yml / refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728) (pull_request) Failing after 0s
sonarcloud.yml / refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728) (pull_request) Failing after 0s
ci.yml / refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728) (push) Failing after 0s
nix.yml / refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728) (push) Failing after 0s
packaging-lint.yml / refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728) (push) Failing after 0s
sonarcloud.yml / refactor: split complex functions in ruby, warichu, pdf text, render text, epub, pdfx (Sonar S3776) (#1728) (push) Failing after 0s
c313c53497
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
alf merged commit c313c53497 into main 2026-10-24 09:49:17 +00:00
alf deleted branch chore/sync-upstream-20261024 2026-10-24 09:49:17 +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!10
No description provided.