mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-28 12:08:46 -06:00
* M4: rename colliding form field names when pages are imported or combined
Insert Pages from File, Combine Files and the grouped combine registered
incoming form fields under names the destination already used, silently
blurring them into one field (fields of one fully-qualified name are one
field, so their values mix). Importing now walks both sides' fully
qualified names (parent.T.child) — including names that hang only off
page widgets, which /AcroForm never lists — and renames a colliding
field's own /T to the first free variant (Text1-1, Text1-2, …), so its
children keep their place in the tree and the second of two colliding
incoming fields is renamed too.
A field_conflicts policy (rename by default; merge keeps the older
behaviour) and reporting — ImportOutcome::renamed_fields, the combine
outcomes, and a field_name_conflicts(dst, src) pre-scan — let callers
choose and prepare; engine, tool and Combine-tab wiring follow.
* M4: engine and tool wiring for renamed field names
Insert Pages from File carries a field_conflicts policy (rename by
default) and reports what it renamed: a repair-log note names each
old → new pair and warns that scripts referring to the old names were
not rewritten, and the undo step's label counts the renames, so nothing
is slipped in silently. Undo restores the original names, as ever.
The session's combine paths gain reporting variants —
combine_unlocked_reporting, combine_grouped_reporting — returning the
bytes and the renames, and doc_combine takes field_conflicts
("rename" | "merge") and lists renamed_fields [[old, new], …] in its
result when fields were renamed, so agents can find what their scripts
must call the field now.
* M4: the Combine tab warns before combining that field names collide
The Warnings column previews, per file, the form fields whose names
collide with earlier files' and will be renamed (Text1 → Text1-1, …),
computed once per list by a new in-order pre-scan (organize
combine_field_conflicts over the whole list, engine wrapper over the
tab's byte sources; a file that cannot be opened previews as nothing,
as its row already says why). The message is plural-aware and
translated in all sixteen catalogs.
* M4: parity for renamed field names on combine and insert
organize.field-name-conflicts ships: rename by fully-qualified name
(or merge, on request), reported everywhere it happens — repair log
and undo label on insert, doc_combine's result, the Combine tab's
warning column. The notes say what is still missing: the tab's preview
ignores narrowed page ranges, the UI offers no merge choice,
Create ▸ Multiple files renames silently, and scripts and XFA bindings
that reference old names are never rewritten.
* M4: review fixes for the field-name conflict work
Four findings from the PR's code review:
- Clippy: the -D warnings gate failed on the new engine tests (a
format! with no interpolation, two drop(doc) no-ops on a
reference); the branch could not pass its own CI.
- The Combine tab's preview warned that a file split into parts
collides with itself: the preview made one source per row, while
the combine groups parts of one file and imports it once. The
preview now dedupes by group (each group's first entry stands for
the file, as the combine does), and every part shows the file's
preview.
- Collision detection compared /T bytes, so one name written in two
encodings (PDFDocEncoding, UTF-16BE) did not collide — the exact
silent blur this work exists to prevent — and renaming a UTF-16BE
name rewrote it as from_utf8_lossy mojibake. Names are now compared,
suffixed and written as decoded text (PdfString::to_text /
PdfString::text), which is also how the forms crate reads them.
- The engine's combine_unlocked/combine_grouped duplicated their
_reporting twins line for line; they now delegate with the Rename
policy, as organize's own wrappers already did.
* Field-name conflicts: only Combine and Insert from File rename
import_pages (Duplicate, Replace) and extract_pages (Extract, Split) go back to Merge, so
copies of a document's own fields keep their names and a source with two same-named field
roots isn't split apart. Pasting pages into the document they were copied from also merges;
pasting into another document renames as Insert from File does. Regression tests for
duplicate, replace, extract/split (organize), duplicate (engine) and paste (ui-egui); the
PR's rename tests call import_pages_with(Rename) explicitly.
Merge fix-up: main made edit labels a translatable Label, so the rename suffix is now two
wordings in EDIT_LABELS ("Insert pages from {name} — 1 field renamed" / "— fields
renamed"), translated in all 20 catalogs. The Combine warning's @plural row is added to
el, kk, sl and tr. Catalog hashes refreshed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>