mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-14 19:27:04 -04:00
3d2bdfe71ada10f6bc39afc680dce61bbf080cbc
51
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3d2bdfe71a |
feat(i18n): add complete Turkish interface language support (#1057)
* feat(i18n): add complete Turkish interface language support * Turkish: rows for the labels that landed alongside this catalog; refresh hashes --------- Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
d1980ec99f |
M14: Kazakh interface language (#955)
* M14: Kazakh interface language A complete clean-room Kazakh (kk) translation of the interface: 2105 catalogue rows covering every English key (commands, tool catalogue, UI literals), with the plural forms and the DATE_LANGUAGES entry (months, months_short, weekdays) the other languages have. - Register 'kk' (Қазақша) in LANGUAGES; every kk-* locale resolves to it, and it appears in Preferences and the date-language picker. - Three coverage tests cloned from the Ukrainian battery: every registered command and All tools label, every tl! literal in the UI sources, and no untranslated English left (format-only strings excepted). - tests/fonts.rs covers the catalogue's Kazakh Cyrillic (әғқңөұүһі) against Inter and JetBrains Mono, which both carry the letters. - ATTRIBUTION.toml gains the kk.tsv entry (contributor-original, MIT OR Apache-2.0). cargo test -p pdfcraft-ui-egui (lib 171 + fonts 7), clippy -D warnings, cargo fmt --check and cargo xtask assets all pass. * Tests: give the Kazakh literal check its own doc comment and restore the Ukrainian one * Kazakh: rows for the labels that landed alongside this catalog; refresh hashes --------- Co-authored-by: pechnikov2026-star <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
58ae136267 |
Add Greek (el) interface localization (#994)
* feat(i18n): add Greek localization * Greek: same place in both language lists, covered by the font test; Μαΐ * Greek: rows for the labels that landed alongside this catalog; refresh hashes --------- Co-authored-by: George Athenakis <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
a0d68dafd2 |
M14: Slovenian (Slovenščina) interface language (#1091)
* Add Slovenian translation * Slovene: a date language for the date picker; drop two stale PRINTCRAFT_MODELS rows * Slovene: rows for the labels that landed alongside this catalog; refresh hashes --------- Co-authored-by: spacekomet <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
cc344a26de |
Typed signatures draw Cyrillic and Greek letters (#846) (#963)
Dancing Script, the typed-signature face, is Latin and Vietnamese only, so script_outline skipped every Cyrillic or Greek character and a Serbian Cyrillic name came out empty. Characters the script lacks are now drawn from the bundled Inter Regular, slanted about 12 degrees and scaled to the script's capital height. Characters neither face has are still skipped. Inter's bytes are now exported as pdfcraft_fonts::INTER_REGULAR and the UI uses that static, so the font is still embedded once. Co-authored-by: DWAA1660 <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
046df9dfe4 |
UI: theme picker with light and dark theme cards (#1082)
* UI: theme picker with light and dark theme cards * UI: update the icon count and the theme test for the cycling theme button --------- Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
892f0b78f0 |
M14: give Windows PDF files a dedicated document icon (#890)
* M14: give Windows PDF files a dedicated document icon Embed the document icon as resource 2 through the existing Windows resource build and select it in both PDF association registrations. Keep the asset reproducible and carry its required licence notices in Windows packages. Formatting, strict Clippy, 1,842 existing workspace tests, all 30 WASM crate checks, assets, layering and parity pass. The Windows x64 release package checks pass, and the contributor confirmed the icon in Explorer. Co-authored-by: Codex <[email protected]> * Refresh catalog hashes after merging main --------- Co-authored-by: Codex <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
603cefe213 |
M14: Add Polish interface language (#782)
* M14: Add Polish interface language * Polish catalog: attribution entry; format the Polish date names * Polish catalog: keyboard key names * Refresh catalog hashes after merging main --------- Co-authored-by: Brandon Thomas <[email protected]> |
||
|
+21 |
26dec1030b |
Combine files: expand a file into its pages (2 of 3, refs #611) (#788)
* Combine files: a thumbnail grid, card sizes and card actions (refs #611) Combine files shows each file as a card (the default; Grid/List kept in the settings, --combine-view): the first page it adds, stacked when it adds more, its name shortened in the middle. Cards select (click, Ctrl, Shift, arrows by card and by row), drag to reorder (one undo step; the grid scrolls at its edges) and share the list's toolbar, selection and history. Locked, unreadable, bad-range and unmeasurable files say why. Thumbnails render off the UI thread, only for cards in view: at most three render threads at once, counted until they exit (no watchdog replacements), a 32 MB texture budget, keys that never show another page, password or file, and one heavy step per frame on the web. Cards are sized from 60% to 200% (toolbar slider and buttons, Ctrl +/-/0, Ctrl+wheel or pinch over the grid, kept in the settings, --combine-zoom), keeping the card under the pointer in place. Hovering a card shows its actions over the top of its page: remove that file, and a magnifier that shows it large, flipping through the pages it adds; the same on a right click, and Space by keyboard. The toolbar wraps between groups at narrow widths. RenderPool gains retire(), without_replacements() and threads() so a caller can bound the render threads that exist at once. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Combine files: expand a file into its pages (refs #611) A file that adds more than one page (up to 2000) expands into a card per page it adds, in its range's order, each labelled with its page and the file's name, on a shared tinted band: from its card's hover bar, a right click, or Expand all / Collapse all in the toolbar. A page card's magnifier opens the preview on that page; Up and Down step rows of cards. Expanding is a view: not an undo step, kept across views and zoom, and the combined file is the same either way. Thumbnails are now kept per file and page, looked up on demand (the cost follows the files, not the pages of an expanded file), and a render's document stays open for two seconds so the next page of the same file isn't read again. Adds the Lucide minimize-2 icon (ISC, recorded in ATTRIBUTION). Co-Authored-By: Claude Opus 5.5 <[email protected]> * Progress docs: target-app parity, gaps, alpha gate, readiness by audience (#873) Progress docs per craftrules standards/progress-docs.md: target-app parity, gaps, roadmap with alpha gate, readiness by audience (full / mainstream / essentials) with Opus 5.5 hours, and feature, format, PDF-spec, hardware, UI and localization parity docs. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Measure: snap to the implicit closing edge of filled paths (#803) (#862) * fix(organize): reject rotation angles that are not multiples of 90 (#801) (#833) Page rotation only turns in quarter steps, but the degree value was read with an integer division by 90 that threw the remainder away. Asking for 45 degrees saved an unrotated page, 91 and 135 saved a 90 degree turn, and the command still reported success. Reject the value before touching the document instead, so every caller gets an actionable error and the pages are left alone. The automation tool already rejected it; the single edit command did not. Fixes #801. Co-authored-by: Big Pickle <[email protected]> * Autosave: snapshot a new unsaved document before its first edit (#815) (#850) * OCR: Recognize text in multiple files refuses paths outside the root (#795) ocr_recognize_files turned a path outside the automation root into a per-file error and returned success, so no_tool_escapes_the_root reported 9 leaks once the OCR models were installed. Without them, loading the models failed first and hid it, and CI never installs them. Every path is now checked before any work starts, and one outside the root refuses the whole call, like the other tools. A missing file inside the root stays a per-file error. Nothing was ever read from outside the root. ocr_recognize_files_refuses_paths_outside_the_root checks this without the models. Co-authored-by: Claude Opus 5.5 <[email protected]> * fix(text): match phrases across repeated whitespace (#814) (#831) The phrase search collapsed runs of whitespace in the query but not in the page text it was matching against, so a document drawn with two space glyphs in a row like the issue example never matched the phrase. Single words still matched, which is why it looked like only some files were affected. Collapse whitespace while the text is flattened, the same way the query is normalised. The regression test fails on the old code because the phrase find returns an empty range, and it also covers tabs and single word queries. Fixes #814. Co-authored-by: Big Pickle <[email protected]> * fix(edit): keep a comment whose appearance is missing when flattening (#805) (#838) Viewers draw notes, FreeText, ink and stamps from their dictionary when the file stores no /AP /N. flatten only drew annotations that already had an appearance and then removed the rest, so a supported note disappeared and the saved page came back blank. Build the appearance a viewer would show for every selected, visible, non-widget annotation that has none, then draw it as usual. A subtype this build cannot render still fails to build and is handled exactly as before. The new synthetic test draws the note icon into the page and asserts it is baked in; without the fix flatten reports 0 drawn and the icon is lost. Co-authored-by: Big Pickle <[email protected]> * fix(comments): keep a reply to a reply in the comment listing (#806) (#839) comment_list collected only the replies whose /IRT pointed at the root comment, so a reply to a reply was listed nowhere at all. Roots and the root count were already right; the nested reply was simply dropped from its thread. Follow the /IRT chain to any depth, with a bound, so every reply under a comment is listed in document order. A reply to a reply now stays discoverable through the tool that promises every comment and its replies. The new test builds a root note, a direct reply and a reply to that reply, then checks both texts are listed and the two notes stay roots. It listed only the direct reply before the fix. Co-authored-by: Big Pickle <[email protected]> * Issue #774: keep the catalog out of object streams in encrypted files (Acrobat) (#836) Acrobat reports an encrypted PDF as "damaged and could not be repaired", before asking for the password, when the document catalog sits in an object stream. Every other reader tried (qpdf, pypdf, poppler, PDFKit, PdfCraft) accepts such files, and qpdf keeps the catalog standalone too. Full saves of encrypted documents now write the catalog as its own object; unencrypted output is unchanged. Verified with Acrobat DC on macOS: the same file fails with the catalog packed and opens with it standalone, in AES-256 and RC4-128. Claude-Session: https://claude.ai/code/session_01REz7wTfQgnopyvN9eQJJVu Co-authored-by: Tristan von Kries <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]> * fix(edit): refuse a header start number that would wrap the next page (#804) (#834) Page numbering adds the start number to the position of the page in the run. At the top of the u32 range that addition wrapped, so a release build saved zero for the second page and still reported success, and a debug build hit a caught overflow error instead. Check the whole run before drawing anything. When the last page number would pass the u32 limit the operation returns an actionable error and the document keeps no header, rather than a half applied run. Fixes #804. Co-authored-by: Big Pickle <[email protected]> * OCR: a scanned euro sign reads as €, not E (#796) The ocrs crate's default alphabet has an E where its recognition model was trained with € (ocrs-models DEFAULT_ALPHABET), so a scanned "€250" was recognised as "E250". pdfcraft-ocr now gives ocrs the alphabet the model was trained with. the_alphabet_is_the_trained_one checks the alphabet without the models; recognize_text_reads_the_euro_sign reads a scan end to end when they are installed. Co-authored-by: Claude Opus 5.5 <[email protected]> * fix(comments): include replies to replies in the comment summary (#820) (#840) The comment summary gathered a comment's direct replies only, matching /IRT against the comment itself. A reply to a reply points at the direct reply, so its text never reached the generated summary even though the stored discussion kept it. Replies are now walked to any depth, with a bound, and indented one level per reply. The existing output for direct replies is unchanged. The new test builds a rectangle, a reply and a reply to that reply, then checks the summary carries both texts with the nested one indented under its parent. It omitted the nested reply before the fix. Co-authored-by: Big Pickle <[email protected]> * fix(xfdf): drop the replaced note's popup when re-importing a comment (#807) (#860) * fix(view): check Shift-Command-G before Command-G for find navigation (#810) (#835) * view: check Shift-Command-G before Command-G for find navigation (#810) * Tests: the find shortcut test waits for find by a deadline (cherry picked from commit eaf3180bd8ebb353b3d8c5ca7b9ef7548ed55c37) --------- Co-authored-by: Brandon Thomas <[email protected]> * fix(editing): recognize paragraph drafts as unsaved work (#811) (#843) * view: check Shift-Command-G before Command-G for find navigation (#810) * fix: recognize paragraph drafts as unsaved work (Issue #811) --------- Co-authored-by: Brandon Thomas <[email protected]> * fix(automation): retain batch results with identical filenames (#877) * fix(automation): retain batch results with identical filenames * Format --------- Co-authored-by: Brandon Thomas <[email protected]> * M13: preserve desktop Action Wizard batch results (#886) * M13: preserve desktop Action Wizard batch results Co-Authored-By: Codex <[email protected]> * ROADMAP: date the desktop action outputs entry today --------- Co-authored-by: Tevinhead <[email protected]> Co-authored-by: Codex <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> * Fit to width fits the shown page in single-page view (#808) (#859) * fix(links): find URLs when lowercasing changes the text length (#816) (#830) find_urls case-folded a copy of the page text and then sliced the original characters with offsets taken from that copy. Case folding can change a string's length — U+0130 (İ) lowercases to "i" plus a combining dot — so the offsets drifted past the end of the source and `chars[i..j]` panicked. The CLI exited 101 before it could create the link; MCP reported an internal tool error but kept serving. Match the ASCII prefixes case-insensitively against the original characters instead, so every offset stays in the source's own index space, and use get() so no lookup can index past the end. A new test reproduces the reported panic on the old code (range start index 41 out of range for slice of length 39) and passes with the fix. pdfcraft-annot's tests, clippy and rustfmt are green. Fixes #816. Co-authored-by: Big Pickle <[email protected]> * organize: deleting the opening page drops the catalog OpenAction (#821) (#855) * fix(text): Turkish dotted and dotless i match in case-insensitive search (#892) Case-insensitive search folded the query and the page with str::to_lowercase, which follows no locale: U+0130 (İ) becomes "i" plus a combining dot above (two characters) and U+0131 (ı) has no case pair. So "istanbul" never found "İSTANBUL", and "ırmak"/"kış" never found "IRMAK"/"KIŞ" (or the reverse). The same PageText::find serves Find, Search & Redact (phrases and word lists) and the automation text search, so Turkish words could also be left unredacted. Fold I, i, İ and ı to "i" and every other character with its own lowercase, one character for one character. Case-sensitive search is unchanged. * XFDF keeps polygon and polyline vertices (#809) (#848) Export wrote polygon and polyline comments without their points and import had nowhere to read them from, so an XFDF round trip left the comments with no /Vertices and no appearance. Export now writes the points as XFDF <vertices>x,y;x,y;…</vertices>, and import reads them back (whole x,y pairs only) before the appearance is drawn. Co-authored-by: DWAA1660 <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> * XFDF keeps a callout's leader, text-box inset, intent and arrowhead (#819) (#854) Co-authored-by: Brandon Thomas <[email protected]> * Web: warn before reloading a document with unsaved changes (#812) (#856) * Issue #813: a cancelled recovery password no longer attaches to the next unlocked document (#858) Recovering an encrypted snapshot parked its metadata in `pending_recovered` until the password prompt was answered. Cancel left it there, and the next encrypted document unlocked in the foreground took the snapshot's original path and recovery key: Save would overwrite the other file and delete its snapshot. The association now travels with the prompt (`PasswordPrompt::recovered`). Cancel puts the entry back on offer and leaves the store alone; a wrong password keeps it on the re-raised prompt; the correct one finishes the recovery of the tab that was just opened. `pending_recovered` is gone. Test: crash with an encrypted snapshot of A, Recover, Cancel, open encrypted B with its password. B keeps its own path and is clean, A's snapshot stays in the store, also after closing B. Fails on main at "B keeps its own path". Co-authored-by: Tristan von Kries <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]> * Viewer: touchpad scrolling tracks the finger 1:1 (#759) (#868) A precision touchpad sends pixel-precise `MouseWheel` events. On Windows they arrive with no `TouchPhase::Start`, so egui never takes its no-smoothing "in touch" path and eases any delta of 8 px or more over several frames, leaving the page a frame behind the finger. The page view now applies precise (Point-unit) wheel input itself, 1:1, through the same un-eased scroll path as keyboard and middle-button auto-scroll, and suppresses egui's eased copy for a short window so its internal easing tail neither doubles nor trails the motion. A coarse mouse wheel (Line/Page units) keeps egui's smoothing, which is pleasant for chunky notches, and single-page paging still owns the vertical axis. Regression test: one 200 px precise swipe scrolls the full 200 px at once (an eased path would ramp there over ~0.1 s) and leaves no drift. Co-authored-by: Justin John <[email protected]> Co-authored-by: Claude Opus 4.8 <[email protected]> * Keep every part when bookmark titles repeat in doc_split (#800) (#863) * Windows: add reproducible security diagnostics for storytold/pdfcraft#747 (#769) Add packaging/windows/security-audit.ps1, a read-only maintainer helper that records a release file's SHA-256, Authenticode status and, with an external YARA binary and rule, every matched string identifier and offset. Document the procedure in docs/releasing.md ("Scanner detections"). No application, dependency, installer or network behaviour changes: the diff touches only the helper and the release documentation. Co-authored-by: Claude Haiku 5.5 <[email protected]> * Notice bar: the message wraps beside its buttons and lines up with them (#785) (#832) The notice bar above the pages (security, forms, XFA, repaired file, warnings, signatures) laid its message out before its buttons. In a narrow document area (a side panel open, a longer translation) the message ran under "Security settings" and on into the side panel, and it wasn't centred on the buttons. A shared notice_bar helper now lays the buttons out first, right to left, centred on a 28 px row, and gives the message the width that's left: it wraps there (cut short with the full text on hover when less than 120 px is left) and its first line is centred on the buttons' row. Regression test: editing::the_security_notice_wraps_beside_its_buttons_and_lines_up_with_them (one line, wrapped and cut-short widths; fails on main). Co-authored-by: DWAA1660 <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]> * M10.2: scan JPEG metadata beyond frame headers (#764) Co-authored-by: Codex <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> * Issue #878: Combine stores an image once when its colour space is an indirect name (#883) ImageMagick writes an image's colour space as its own object (`/ColorSpace 10 0 R`, `10 0 obj /DeviceRGB`). Each source's copy of that object was never merged, since it isn't a resource, so identical images compared unequal and every copy was kept: 8 copies of an 80 MB ImageMagick PDF combined into 648 MB instead of 81 MB. Dedupe now compares a reference to a plain value (name, number, boolean or string) as that value. The value objects themselves are still never merged. Combine, Insert Pages and Reduce File Size share this code. Co-authored-by: Claude Opus 5.5 <[email protected]> * organize: drop named destinations and their links when a page is deleted (#817) (#851) * JavaScript: limit util.printf widths and output, and array arguments (#770) util.printf accumulated a conversion's width and precision with unchecked arithmetic and no maximum, and its output had no bound; the array arguments of resetForm and the field value/colour setters were read for as many items as the array's length says, which a sparse array makes free. Saturate the numbers and refuse widths and precisions above 4096, output above 1 MiB and arrays longer than 2^20 with a script error, before anything is allocated from them. Co-authored-by: Claude Sonnet 5.5 <[email protected]> * Linux: "Use system setting" asks the desktop, not winit (#881) winit reports no system theme on Linux — `ActiveEventLoop::system_theme` is `None` there on every desktop — so `ThemePreference::System` never saw the desktop's choice and silently fell back to whatever was on screen: PdfCraft came up light on a dark desktop, and picking "Use system setting" after Dark kept it dark. The default setting did not follow the system. `pdfcraft-platform` now reads the XDG Desktop Portal's Settings interface off the UI thread and the app follows the answer, including a change made while it runs. The colour scheme is asked for under its GNOME schema name first, which GNOME's and XFCE's portals both answer, then under the older freedesktop one, which KDE answers. A desktop that answers neither leaves the user's own choice alone, exactly as before. Co-authored-by: GyuriX <[email protected]> * Extract/Combine: a page repeated in one selection gets its own annotations (#818) (#852) * M5.7: Fill & Sign tools pick up placed signatures to move and resize them (#822) A signature placed with Fill & Sign could only be moved with the Select tool. While a Fill & Sign tool was active (Sign, Initials, Add text, Check, Date...), hovering the signature showed the placement crosshair, a drag did nothing and a click stamped another mark on top of it. Now, as in Acrobat, a Fill & Sign tool picks up the Fill & Sign marks already on the page: hovering one shows the move cursor, a click selects it, a drag moves it and the selected mark's handles resize it. Away from them the tool places as before, including on other comments. Image signatures keep their live move/resize preview. Comments now carry a fill_sign flag (pdfcraft_annot::is_fill_sign for the engine's list, the same rules in the viewer's inspector), so this also works on reopened files. Co-authored-by: lloyd <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]> * Web: opt-in embedding bridge for host pages (?host=parent) (#842) A page that frames PdfCraft on the same origin can now pass it PDFs and receive saves through postMessage, instead of Save becoming a browser download. Built for a Nextcloud integration, but nothing in it is host-specific. - ui-egui: HostSaveFn/HostDirtyFn hooks (`host_save`, `host_dirty`), None by default. On wasm, Save hands the bytes to `host_save` when set; `host_dirty` hears each frame whether any tab has unsaved work. - pdfcraft-web: `host::Bridge`, enabled only by `?host=parent` inside a frame. Messages: pdfcraft:ready / open / save / dirty / failed; only the parent window on our own origin is heard or answered. `?author=` names comment authors unless the user chose a name. - Test: host_dirty_hears_when_unsaved_work_appears_and_goes. Without `?host=parent` nothing changes. Claude-Session: https://claude.ai/code/session_01G6GtUCaPiCMEQCN4QcdQnp Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> * Print: a scaled annotation appearance no longer prints larger than its rectangle (#802) (#861) * Single instance: enable tab handoff in Windows portable mode (#889) (#891) * Single instance: enable tab handoff in Windows portable mode (#889) * Single instance: a portable copy's socket stays in %LOCALAPPDATA%, under its own name (cherry picked from commit c7db1e80a374e80a11504efefbaac680dfa5e872) --------- Co-authored-by: Brandon Thomas <[email protected]> * Issue #390: build the DMG with hdiutil create so the app passes codesign --strict (#823) * Issue #390: build the DMG with hdiutil create so the app passes codesign --strict makehybrid -hfs wrote a com.apple.FinderInfo (Finder location -1,-1) on every file in the image, and codesign --verify --deep --strict rejects that as "Finder information, or similar detritus", on the app in the DMG and on a copy installed from it. hdiutil create -srcfolder writes the files as they are; it attaches a device while copying, so it gets up to five tries. A gate mounts the finished image read-only and verifies the app inside with --strict. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01REz7wTfQgnopyvN9eQJJVu * Issue #390: retry hdiutil attach and detach in the DMG gate too As suggested in review: the gate mounts the signed image under set -e, so a "Resource busy" there would stop a release after the DMG was built. The same five tries with growing pauses now cover create, attach and detach. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01REz7wTfQgnopyvN9eQJJVu --------- Co-authored-by: Tristan von Kries <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]> * M4: make page-label generation lazy across large documents (#845) * M4: make page-label generation lazy across large documents Page labels were expanded into one String per page, and the whole sequence was refused once the labels passed 4 MiB in total. A valid document with long labels could therefore neither be read nor edited. Add a PageLabels view over the label ranges: label(page) builds one label, and iter() builds the labels one at a time, so no string is kept per page. Edits validate each range from its largest number (Roman numerals by their thousands) instead of building every label, so the check no longer depends on the page count. The per-label length limit, the number-tree work and depth limits and the overflow checks are unchanged. page_labels() keeps its signature and returns the same labels as before for ordinary documents. Co-Authored-By: Claude Haiku 5.5 <[email protected]> * M4: drop the aggregate page-label cap from document inspection Document inspection refused every custom label once their total passed 4 MiB, so a valid document with long labels showed physical page numbers and a warning. Labels are now applied to every page. The per-label length limit, the number-tree work, depth and cycle limits and the prefix bounds are unchanged, and labels are still applied only after every range is accepted. MAX_LABEL_TOTAL_BYTES is removed. The inspector keeps one label per page (PageInfo.label), so its label memory grows with the page count times the label length. The page count is bounded by the objects in the file, and each label by 1,024 bytes. Co-Authored-By: Claude Haiku 5.5 <[email protected]> * M4: keep the inspector's 4 MiB page-label cap until its labels are lazy Commit |
||
|
|
1c33e6f851 |
M14: Arabic interface language (#692)
* M14: Arabic interface language A 2,136-entry Arabic catalog (six CLDR plural forms, Arabic month and weekday names), selected by `ar` and every `ar-*` locale. egui joins Arabic letters but places words left to right, so the catalog is put into display order when it loads (bidi::display_rtl); placeholders, keyboard shortcuts and caption colons stay in place. The command search matches a multi-word Arabic query word by word. The craft-fonts pin moves to the revision with Noto Sans Arabic. crates/fonts/build.rs now refuses to embed Adobe type designs, so the Noto Sans CJK SC in that revision is never embedded (AGENTS.md §1.1). Co-Authored-By: Claude Opus 5.5 <[email protected]> * M14: Arabic catalog follows the {key} shortcut labels and has Redaction code Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
49c6e2ec54 |
i18n: complete Brazilian Portuguese (pt-BR) interface catalog (#604)
* i18n: complete Brazilian Portuguese (pt-BR) interface catalog Catalog by André Cardoso (andrecards) from #288, unioned with the strings merged after the catalog was cut. Asset hash refreshed. * i18n: translate the pt-BR strings added since the #288 catalog and gate coverage * i18n: pt-br review fixes (line ending, redact/sanitize/page-boxes terminology) * i18n: credit the pt-BR translator and document full coverage Name André Cardoso (andrecards) as the pt-br catalog's translator in ATTRIBUTION.toml: the ~1,826-entry gist posted in issue #288, with the labels added since and the wording review as this change's contribution. ATTRIBUTION.md is regenerated from it. docs/localization.md moves Brazilian Portuguese from the menus-only clause into the full-coverage list, states the 1,997-entry count next to the provenance (following the Ukrainian paragraph's pattern), and lists pt-br with the languages whose coverage tests gate every command, All tools label and tl!() literal (added with the catalog). people.toml is unchanged: PR #165's translator has no entry there, and its policy is that only one's own entry may be added. * i18n: pt-br writes '>' like the other Latin catalogs (Inter has no ▸) * i18n: pt-BR final review fixes (toast grammar, contextual entries, menu gate) * pt-BR: add the labels main gained while this catalog was completed (98) and drop stale OCR keys --------- Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
94f9ce69c6 |
i18n: add Italian (it) interface translation (#494)
* i18n: add Italian (it) interface translation - Complete it catalog (about 2,000 entries); it and it_* locales use it - Fonts test covers the Italian catalog; ▸ written as > like fr/es/ru, since Inter has no ▸ - Docs, attribution and ROADMAP Co-Authored-By: Claude Opus 5.5 <[email protected]> * it: add the labels main gained since this catalog (83), drop stale OCR keys, and coverage tests --------- Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
56f85f76df |
M9: more signature validation algorithms (SHA-3, RIPEMD-160, Ed25519, P-521, brainpool, PSS, rsa_sha1) (#386)
* M9: more signature validation algorithms Validation now reads what real signers write, and says when it is weak: - Digests SHA-224, SHA-512/224, SHA-512/256, SHA3-224/256/384/512 and RIPEMD-160, beside SHA-1 and SHA-2. - RSA PKCS#1 v1.5 for every digest, in `rsa_pad`: the one expected encoding is built and compared byte for byte, with or without the DigestInfo's NULL (RFC 8017 App. B.1). A signature over the bare digest, which doesn't say which hash it uses, is refused. The signature value must be below the modulus (RFC 8017 §5.2.2); s and s + n both verified before. - RSA-PSS with the hash, MGF1 hash and salt length the signature declares. - ECDSA as DER, non-minimal DER or raw r||s on P-256, P-384, P-521 and brainpoolP256r1/P384r1/P512r1 (BSI "plain" ECDSA OIDs too); brainpoolP512r1 is hand-written on crypto-bigint because no RustCrypto crate has it. - Ed25519 (RFC 8419), and the legacy adbe.x509.rsa_sha1 format. - An algorithm PdfCraft can't check is Unknown, never Invalid. - SHA-1 and RIPEMD-160 signatures validate, but the signature's details say the algorithm is weak (wording pinned by tests). - Encoding irregularities that were tolerated are listed in the details (`verify_noting`; `verify` keeps its signature). Found while testing, each with a regression test that failed before the fix: a brainpoolP512r1 public key with a coordinate >= p panicked inside crypto-bigint's `sub_mod` (the certificate comes from the PDF); it is refused now, and the point at infinity is an invalid signature, not an error. Vectors were made with OpenSSL (tests/data/README.md has the commands). Co-Authored-By: Claude Sonnet 5.5 <[email protected]> * Update comment to clarify MAC digest restrictions Co-authored-by: Copilot Autofix powered by AI <[email protected]> * M9: a legacy x509.rsa_sha1 signature whose key the verifier rejects is Invalid; only unsupported keys are "can't check yet" Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Sonnet 5.5 <[email protected]> Co-authored-by: Copilot Autofix powered by AI <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
e6df6b1384 |
i18n: add complete Ukrainian interface translation (#509)
* M14: add complete Ukrainian interface translation Add the uk registry entry and original catalog, Ukrainian integer plurals, calendar month inflection, attribution and localization documentation. Fit Home recommendation cards and the search hint to translated text. Cover locale detection, persistence, catalogs, bundled glyphs and UI control. Fixes #503 Related to #348 Co-authored-by: Codex <[email protected]> * uk: add the recent-files labels, labels that reach tl!() through a variable, and 'Inserted text'; fix 'мають мати' * uk: Home / End are key-cap names --------- Co-authored-by: Codex <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
95120862fc |
M14: Hungarian interface catalog (hu) (#545)
* M14: Hungarian interface catalog (hu) Magyar joins the interface languages as a complete catalog, so Preferences and hu locales show commands, dialogs, panels and notices in Hungarian. Wording uses informal "te" and nouns for commands; the strings were written from the meaning of the English labels. * Small grammar correction * hu: restore trailing spaces in run-on labels; add the recent-files labels and labels that reach tl!() through a variable --------- Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
7c358099ff |
M14: German interface catalog (de) (#471)
* M14: German interface catalog (de) Deutsch (`de`) joins the interface languages as a complete catalog of 2,035 entries: every command, All tools entry, dialog, panel and notice. It is selected from Preferences, and Auto picks it for `de`, `de_DE`, `de_AT`, `de_CH` and other German locales. Wording uses the informal "du" and the infinitive for commands; translations are clean-room, written from the meaning of the English labels. - de.tsv registered in LANGUAGES (plural rule one|other) - tests: registration and locale mapping, plurals, coverage of every command, All tools label and tl! literal, history labels keeping user values; the Latin UI faces cover umlauts, ß and German quotes; the control-channel language switch includes `de` - ATTRIBUTION.toml/.md entry (kind = "translation"), docs/localization.md, ROADMAP and parity notes Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * M14: register German as the 12th language; translate the reopen-session preference (de, bg) Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
37542ad9db |
Merge remote-tracking branch 'origin/main' into dmg-background
# Conflicts: # ATTRIBUTION.md |
||
|
|
79eadc2aa8 |
M14: Bulgarian (Български) interface language (#466)
A complete clean-room catalog (2,035 entries: every command, All tools label and tl! literal), registered as `bg` with one/other plurals so Auto picks it on Bulgarian systems. Tests mirror the Russian ones (registration, plurals, persistence, command and literal coverage), and Bulgarian joins the Latin/Cyrillic font-coverage test. Co-authored-by: Claude Opus 5.5 <[email protected]> |
||
|
|
084f7636ea |
macOS DMG: branded window background and icon layout
The DMG opened as a plain Finder window. It now shows the app icon's figure on the PdfCraft colour, with PdfCraft.app and the Applications link side by side. Same approach as PhotoCraft's and VectorCraft's. - packaging/macos/dmg/: background.svg (source; text outlined, no paper grain, the figure an <image> of assets/app-icon), background.tiff (1x + 2x HiDPI, 16-colour palette, Deflate, sRGB; ~95 KB) and dmg-layout.DS_Store (Finder view settings: window, icon size 128, positions, background). - generate.py writes the TIFF and the layout on any OS, byte-for-byte reproducible, with nothing from the machine that ran it. - package.sh copies them into the staging folder; the image is still built with hdiutil makehybrid. Nothing extra runs in the signing job. - The volume name drops the version: the layout finds the background through an alias that includes the volume name. The DMG file name keeps the version. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
31f3631868 |
Home: pin folders and list their newest PDFs (#383)
* Home: pin folders and list their newest PDFs
File > Pin folder to Home... (or "Pin a folder..." on Home) pins up to 8
folders. Each lists its newest PDFs with how long ago and size, opens one
with a click, and can be unpinned. Folders are read on a worker thread and
listed again every few seconds while Home shows, so new scans appear by
themselves; an unreadable folder (moved, offline synced drive) stays pinned
and says so. A folder is described by where it is ("iCloud Drive",
"OneDrive - Contoso", "Documents > Work") instead of its full path.
Cloud drives work through their local synced folder; nothing goes through a
provider API. Settings keep absolute paths only, deduplicated and capped.
Tests: crates/ui-egui/tests/folders.rs (8) and folders_ui unit tests (4).
Command label translated in every catalog; Home strings in fr, es, ja,
zh-hans and zh-hant; catalog hashes updated in ATTRIBUTION.toml.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Add my contributor name (amitabhthakur)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Home pinned folders: Russian strings; regenerate ATTRIBUTION.md
The Russian catalog (#375) landed while this branch was open: its coverage
tests need the new command label and Home strings. ATTRIBUTION.md is
regenerated (cargo xtask assets --write), which also adds the ru.tsv row
that #375 left out.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
|
||
|
|
05c8ab3b3e |
M14: Telugu (తెలుగు) interface language (#349)
* M14: Telugu interface font - The interface takes `Telu` faces from craft-fonts after the CJK and Arabic ones, on the web too - Test: Telugu text has glyphs in every family and its conjuncts are shaped Signed-off-by: Chiranjeevi U <[email protected]> * M14: Telugu interface language - Complete te catalog: 1,984 entries plus whole-phrase Undo/Redo; te and te_IN locales use it - Undo and Redo labels use a catalog phrase when the language has one (Telugu puts the verb last) - Tests, docs, attribution, parity and ROADMAP Signed-off-by: Chiranjeevi U <[email protected]> * Add my contributor name (chiranjeevi-max) Signed-off-by: Chiranjeevi U <[email protected]> * M14: catalog contexts for labels with two meanings - tl_ctx! gives the signature pad's Type, the Action Wizard's Start and the comment menu's Edit their own context; Telugu translates them, other languages keep their current translation - Preferences' All tools goes through the catalog in every language Signed-off-by: Chiranjeevi U <[email protected]> * M14: Telugu for the look-alike web address warnings Signed-off-by: Chiranjeevi U <[email protected]> * M14: Telugu for the image signature notices Signed-off-by: Chiranjeevi U <[email protected]> * Telugu for Open Recent (#323) Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Signed-off-by: Chiranjeevi U <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]> |
||
|
|
cd8c753527 |
M14: French interface catalog (#291)
Add Français (fr) as a complete UI catalog and select it for every French locale. Preferences lists it, and Auto follows fr, fr_FR, fr_CA and fr_BE. About credits labels now go through the catalog. Coverage tests check commands, All tools labels and every tl! literal. The bundled Latin faces cover the catalog. Co-authored-by: Cursor Agent <[email protected]> Co-authored-by: iMhack <[email protected]> |
||
|
|
4db49900c6 |
Add Spanish (es) interface catalog (#251)
Registers Español in the language list, with a full catalog covering commands, dialogs, panels and notices, plus tests and docs. Claude-Session: https://claude.ai/code/session_01A3kqJC1D3PAgT3dHxnqYNy Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> |
||
|
|
355de9038e |
i18n: Simplified Chinese UI language option (#112)
* i18n: Czech interface language
Adds Czech (Čeština, code `cs`) next to English and Japanese:
Preferences ▸ Interface language, `ui.set language cs`, `ui.state`
and persisted preferences all accept it.
- i18n: `Language::Cs`; `tr()` picks the language's table with a match
(English has none), panic-free. The CZECH table (83 entries) covers
every label passed to `.tr("…")` (main menu, View zoom/theme/side-panel
entries, Preferences dialog), every registered File/Edit/Pages/View/Help
command shown by `registry_menu`, and every key of the Japanese table.
Written clean-room from the English meaning, not from any Acrobat
localisation.
- Tests: Czech covers every registered menu title and label, every
`.tr("…")` literal found by scanning the crate's sources, and the
Japanese keys; nothing is left identical except an explicit KEEP_AS_IS
list ("OK"); ellipses match the source; keys are unique per language;
`cs` round-trips through set_option, ui.set/ui.state and persistence.
- theme: the font setup is split into `font_definitions()`, and a test
checks with skrifa (dev-dependency, already in the tree via egui) that
Inter Regular/Medium/SemiBold and JetBrains Mono draw all Czech letters
and every Czech translation, so nothing falls back to Shippori Mincho.
- The `language` error lists `cs`; docs/localization.md, the parity note
for misc.prefs-language and the ROADMAP log mention Czech.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
* M14: translation catalogs, same system as PhotoCraft
Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).
The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.
Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
* M14: add Traditional Chinese (Taiwan) UI localization
Co-Authored-By: Codex <[email protected]>
* M14: translate shortcuts and expose language preferences in Edit menu
Add command-comma and verify language switching through the actual selector.
Co-authored-by: Codex <[email protected]>
* M14: expand Traditional Chinese dialogs, panels and diagnostics
Preserve opaque values in translated templates and keep application diagnostics at the UI boundary. Extend native control and template regression coverage.
Co-authored-by: Codex <[email protected]>
* M14: finish Traditional Chinese signature prompts and history labels
Translate generated action labels without changing filenames or field names. Complete checkbox styles, resolution labels and native picker filters.
Co-authored-by: Codex <[email protected]>
* M14: complete Japanese dialogs, panels, shortcuts and diagnostics
Expand Japanese from 49 to 1830 interface entries, expose language preferences in the Edit menu, preserve opaque template and history values, and localize known application diagnostics only at the UI boundary. Add control, persistence, template and desktop/web glyph regressions.
Co-authored-by: Codex <[email protected]>
* i18n: Simplified Chinese UI language option
Adds Language::Zh alongside en/ja (--language zh, preferences switch,
persisted): full Chinese translation table covering every user-visible
label, generic Hans font fallback plumbing, and a build.rs skip-guard
plus test so Noto CJK is never embedded (AGENTS.md 1.1). Pairs with
storytold/craft-fonts#5 (ChillRoundF Regular, OFL-1.1 Adobe-free
chain), which supplies the Hans glyphs. Also fixes a startup deadlock
from translating inside lazy widget_info closures.
* i18n: add Brazilian Portuguese (pt-br) UI translation
Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md.
* M14: strict catalog validation, one-pass fmt, translation assets
Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
placeholder, ellipsis and plural-form mismatches and duplicates. The
bundled catalogs must have no errors (tests); at run time a bad line is
still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
`translation` kind that may never come from Adobe; ja.tsv gets its
ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
dirty state and command ids.
Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.
Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Brazilian Portuguese as a TSV catalog
Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv
(same 49 strings, plus Auto) and register it in LANGUAGES with
PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese
locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in
PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and
the docs and parity notes list the new code.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Czech as a TSV catalog
Move #68's Czech table into crates/ui-egui/src/i18n/cs.tsv (PrintCraft
labels renamed PdfCraft, plus Auto) and register it with PhotoCraft's
Czech plural rule (one / few / other). #68's tests become catalog
tests: Czech covers every registered menu title and menu command label,
keeps ellipses, uses no three-dot ellipsis or stray whitespace, and only
leaves "OK" untranslated; the code persists and `cz` is rejected. The
source-scanning `.tr("…")` test is dropped: strings now go through tl!
and the catalog tests check consistency.
The font-coverage test moves to tests/fonts.rs and covers both Latin
catalogs (cs, pt-br) against Inter and JetBrains Mono. It keeps skrifa
as a dev-dependency (the version pdfcraft-fonts already uses): egui's
has_glyphs can't answer it, since a family with only the primary face
also uses that face as its replacement face.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: route every UI string through the catalog; Japanese as ja.tsv
Port #141's wiring to the catalog API from land/106:
- `crate::i18n::tr(ui, s)` becomes `tl!(s)`, `tr_fmt`/`tr_template`
become `i18n::fmt(tl!(..), ..)`, and `Language::get`/`store` (the
egui temp-data copy of the language) are gone: the drawing language
is the per-thread `i18n::current()`, set from the preference at the
start of each frame. Worker threads (export, OCR, batch actions) take
the UI's language with them for their summaries.
- ja.rs (1,830 pairs) becomes ja.tsv, merged with the existing entries
and renamed PrintCraft -> PdfCraft. The 29 diagnostic templates of
errors.rs are dropped.
- `Language::diagnostic` and errors.rs are dropped: matching engine and
OS messages against English templates breaks silently whenever the
wording changes. Error details are shown as they are, inside the
translated frame ("{label} failed: {e}").
- History labels (`command_label`/`action_label`) move into i18n and keep
captured file and field names; registry menus prefer `@id` entries.
- Preferences: Auto plus every registered language, relabelled at once.
- Tests: Japanese covers every command and All tools entry; Japanese
labels have glyphs with the desktop faces and with the web subset
(with craft-fonts); history labels; #141's control tests, with the
error-detail expectation updated.
Co-Authored-By: shuiyue-cmyk <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Preferences in the Edit menu, Cmd/Ctrl-comma
Split out of #141: register app.preferences in the Edit menu with the
platform's usual shortcut (Command-comma on macOS, Ctrl-comma
elsewhere), so the interface language can be found and changed with no
document open. Shortcut keys may now be punctuation (egui's key name
","). #141's control test drives the menu item, the language selector
and the shortcut in Japanese and English.
Co-Authored-By: sakamoto824 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Traditional Chinese as zh-hant.tsv
Reduce #140 to its translations: zh_tw.rs becomes
crates/ui-egui/src/i18n/zh-hant.tsv (PrintCraft renamed PdfCraft; the
29 errors.rs diagnostic templates dropped, as for Japanese) and one
registry row, code `zh-hant` (Taiwan vocabulary). Locales zh_TW, zh_HK,
zh_MO and zh-Hant-* resolve to it. #140's own copy of the UI wiring and
its errors.rs diagnostics are not taken: land/141 carries the wiring.
Tests: registration, locale mapping, every command label translated.
The catalog is an attributed asset; docs, ROADMAP and parity list it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Simplified Chinese as zh-hans.tsv
Reduce #112's translations to crates/ui-egui/src/i18n/zh-hans.tsv
(PrintCraft renamed PdfCraft) and one registry row, code `zh-hans`
(#112 used `zh`; `zh`, `zh_CN`, `zh_SG` and `zh-Hans` locales still
resolve to it through the system-language match). #112's own copy of
the UI wiring is superseded by land/141. Tests: registration, locale
mapping, menu coverage. The catalog is an attributed asset; docs,
ROADMAP and parity list it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: CJK font order follows the UI language
From #112: `ui_cjk_fonts(prefer_hans)` orders the craft-fonts CJK faces
for the interface, and `theme::font_definitions_for` installs them. In
Simplified Chinese the `Hans` faces come first; otherwise the Japanese
ones (the previous behaviour). egui draws each character with the first
face that has it, so with Japanese first a Simplified-only character
(欢) would land in another face and sit on a different baseline. The
fonts are reinstalled when the language crosses that line (same family
names, so named fonts stay valid while the new set loads).
Changes from #112: within each group BIZ UDPGothic still leads, so a
serif listed first in the manifest (Shippori Mincho) never becomes the
Chinese-mode UI fallback; the unused `document_chinese_font` is left
out; and the crates/fonts/build.rs special case that skipped
"Noto Sans CJK SC" (and its test assertion and README line) is not
taken. Without CRAFT_FONTS_DIR, or without a `Hans` face, the order
logic yields only what exists: Chinese characters then show replacement
boxes and nothing panics (tests/fonts.rs, the fonts crate test, and the
control test switching ja -> zh-hans -> en).
Also document `--language` on the app's command line.
Co-Authored-By: shuiyue-cmyk <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Petr Leo Compel <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: sakamoto824 <[email protected]>
Co-authored-by: Codex <[email protected]>
Co-authored-by: shuiyue-cmyk <[email protected]>
Co-authored-by: RicSchonfelder <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
|
||
|
|
ab4c87926a |
M14: expand Traditional Chinese UI, dialogs and language preferences (#140)
* i18n: Czech interface language
Adds Czech (Čeština, code `cs`) next to English and Japanese:
Preferences ▸ Interface language, `ui.set language cs`, `ui.state`
and persisted preferences all accept it.
- i18n: `Language::Cs`; `tr()` picks the language's table with a match
(English has none), panic-free. The CZECH table (83 entries) covers
every label passed to `.tr("…")` (main menu, View zoom/theme/side-panel
entries, Preferences dialog), every registered File/Edit/Pages/View/Help
command shown by `registry_menu`, and every key of the Japanese table.
Written clean-room from the English meaning, not from any Acrobat
localisation.
- Tests: Czech covers every registered menu title and label, every
`.tr("…")` literal found by scanning the crate's sources, and the
Japanese keys; nothing is left identical except an explicit KEEP_AS_IS
list ("OK"); ellipses match the source; keys are unique per language;
`cs` round-trips through set_option, ui.set/ui.state and persistence.
- theme: the font setup is split into `font_definitions()`, and a test
checks with skrifa (dev-dependency, already in the tree via egui) that
Inter Regular/Medium/SemiBold and JetBrains Mono draw all Czech letters
and every Czech translation, so nothing falls back to Shippori Mincho.
- The `language` error lists `cs`; docs/localization.md, the parity note
for misc.prefs-language and the ROADMAP log mention Czech.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
* M14: translation catalogs, same system as PhotoCraft
Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).
The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.
Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
* M14: add Traditional Chinese (Taiwan) UI localization
Co-Authored-By: Codex <[email protected]>
* M14: translate shortcuts and expose language preferences in Edit menu
Add command-comma and verify language switching through the actual selector.
Co-authored-by: Codex <[email protected]>
* M14: expand Traditional Chinese dialogs, panels and diagnostics
Preserve opaque values in translated templates and keep application diagnostics at the UI boundary. Extend native control and template regression coverage.
Co-authored-by: Codex <[email protected]>
* M14: finish Traditional Chinese signature prompts and history labels
Translate generated action labels without changing filenames or field names. Complete checkbox styles, resolution labels and native picker filters.
Co-authored-by: Codex <[email protected]>
* M14: complete Japanese dialogs, panels, shortcuts and diagnostics
Expand Japanese from 49 to 1830 interface entries, expose language preferences in the Edit menu, preserve opaque template and history values, and localize known application diagnostics only at the UI boundary. Add control, persistence, template and desktop/web glyph regressions.
Co-authored-by: Codex <[email protected]>
* i18n: add Brazilian Portuguese (pt-br) UI translation
Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md.
* M14: strict catalog validation, one-pass fmt, translation assets
Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
placeholder, ellipsis and plural-form mismatches and duplicates. The
bundled catalogs must have no errors (tests); at run time a bad line is
still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
`translation` kind that may never come from Adobe; ja.tsv gets its
ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
dirty state and command ids.
Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.
Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Brazilian Portuguese as a TSV catalog
Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv
(same 49 strings, plus Auto) and register it in LANGUAGES with
PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese
locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in
PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and
the docs and parity notes list the new code.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Czech as a TSV catalog
Move #68's Czech table into crates/ui-egui/src/i18n/cs.tsv (PrintCraft
labels renamed PdfCraft, plus Auto) and register it with PhotoCraft's
Czech plural rule (one / few / other). #68's tests become catalog
tests: Czech covers every registered menu title and menu command label,
keeps ellipses, uses no three-dot ellipsis or stray whitespace, and only
leaves "OK" untranslated; the code persists and `cz` is rejected. The
source-scanning `.tr("…")` test is dropped: strings now go through tl!
and the catalog tests check consistency.
The font-coverage test moves to tests/fonts.rs and covers both Latin
catalogs (cs, pt-br) against Inter and JetBrains Mono. It keeps skrifa
as a dev-dependency (the version pdfcraft-fonts already uses): egui's
has_glyphs can't answer it, since a family with only the primary face
also uses that face as its replacement face.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: route every UI string through the catalog; Japanese as ja.tsv
Port #141's wiring to the catalog API from land/106:
- `crate::i18n::tr(ui, s)` becomes `tl!(s)`, `tr_fmt`/`tr_template`
become `i18n::fmt(tl!(..), ..)`, and `Language::get`/`store` (the
egui temp-data copy of the language) are gone: the drawing language
is the per-thread `i18n::current()`, set from the preference at the
start of each frame. Worker threads (export, OCR, batch actions) take
the UI's language with them for their summaries.
- ja.rs (1,830 pairs) becomes ja.tsv, merged with the existing entries
and renamed PrintCraft -> PdfCraft. The 29 diagnostic templates of
errors.rs are dropped.
- `Language::diagnostic` and errors.rs are dropped: matching engine and
OS messages against English templates breaks silently whenever the
wording changes. Error details are shown as they are, inside the
translated frame ("{label} failed: {e}").
- History labels (`command_label`/`action_label`) move into i18n and keep
captured file and field names; registry menus prefer `@id` entries.
- Preferences: Auto plus every registered language, relabelled at once.
- Tests: Japanese covers every command and All tools entry; Japanese
labels have glyphs with the desktop faces and with the web subset
(with craft-fonts); history labels; #141's control tests, with the
error-detail expectation updated.
Co-Authored-By: shuiyue-cmyk <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Preferences in the Edit menu, Cmd/Ctrl-comma
Split out of #141: register app.preferences in the Edit menu with the
platform's usual shortcut (Command-comma on macOS, Ctrl-comma
elsewhere), so the interface language can be found and changed with no
document open. Shortcut keys may now be punctuation (egui's key name
","). #141's control test drives the menu item, the language selector
and the shortcut in Japanese and English.
Co-Authored-By: sakamoto824 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Traditional Chinese as zh-hant.tsv
Reduce #140 to its translations: zh_tw.rs becomes
crates/ui-egui/src/i18n/zh-hant.tsv (PrintCraft renamed PdfCraft; the
29 errors.rs diagnostic templates dropped, as for Japanese) and one
registry row, code `zh-hant` (Taiwan vocabulary). Locales zh_TW, zh_HK,
zh_MO and zh-Hant-* resolve to it. #140's own copy of the UI wiring and
its errors.rs diagnostics are not taken: land/141 carries the wiring.
Tests: registration, locale mapping, every command label translated.
The catalog is an attributed asset; docs, ROADMAP and parity list it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Petr Leo Compel <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: Codex <[email protected]>
Co-authored-by: RicSchonfelder <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
Co-authored-by: shuiyue-cmyk <[email protected]>
|
||
|
|
f0f923b82e |
i18n: Czech interface language (#68)
* i18n: Czech interface language
Adds Czech (Čeština, code `cs`) next to English and Japanese:
Preferences ▸ Interface language, `ui.set language cs`, `ui.state`
and persisted preferences all accept it.
- i18n: `Language::Cs`; `tr()` picks the language's table with a match
(English has none), panic-free. The CZECH table (83 entries) covers
every label passed to `.tr("…")` (main menu, View zoom/theme/side-panel
entries, Preferences dialog), every registered File/Edit/Pages/View/Help
command shown by `registry_menu`, and every key of the Japanese table.
Written clean-room from the English meaning, not from any Acrobat
localisation.
- Tests: Czech covers every registered menu title and label, every
`.tr("…")` literal found by scanning the crate's sources, and the
Japanese keys; nothing is left identical except an explicit KEEP_AS_IS
list ("OK"); ellipses match the source; keys are unique per language;
`cs` round-trips through set_option, ui.set/ui.state and persistence.
- theme: the font setup is split into `font_definitions()`, and a test
checks with skrifa (dev-dependency, already in the tree via egui) that
Inter Regular/Medium/SemiBold and JetBrains Mono draw all Czech letters
and every Czech translation, so nothing falls back to Shippori Mincho.
- The `language` error lists `cs`; docs/localization.md, the parity note
for misc.prefs-language and the ROADMAP log mention Czech.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
* M14: translation catalogs, same system as PhotoCraft
Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).
The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.
Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
* i18n: add Brazilian Portuguese (pt-br) UI translation
Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md.
* M14: strict catalog validation, one-pass fmt, translation assets
Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
placeholder, ellipsis and plural-form mismatches and duplicates. The
bundled catalogs must have no errors (tests); at run time a bad line is
still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
`translation` kind that may never come from Adobe; ja.tsv gets its
ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
dirty state and command ids.
Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.
Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Brazilian Portuguese as a TSV catalog
Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv
(same 49 strings, plus Auto) and register it in LANGUAGES with
PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese
locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in
PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and
the docs and parity notes list the new code.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* M14: Czech as a TSV catalog
Move #68's Czech table into crates/ui-egui/src/i18n/cs.tsv (PrintCraft
labels renamed PdfCraft, plus Auto) and register it with PhotoCraft's
Czech plural rule (one / few / other). #68's tests become catalog
tests: Czech covers every registered menu title and menu command label,
keeps ellipses, uses no three-dot ellipsis or stray whitespace, and only
leaves "OK" untranslated; the code persists and `cz` is rejected. The
source-scanning `.tr("…")` test is dropped: strings now go through tl!
and the catalog tests check consistency.
The font-coverage test moves to tests/fonts.rs and covers both Latin
catalogs (cs, pt-br) against Inter and JetBrains Mono. It keeps skrifa
as a dev-dependency (the version pdfcraft-fonts already uses): egui's
has_glyphs can't answer it, since a family with only the primary face
also uses that face as its replacement face.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: RicSchonfelder <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
|
||
|
|
41734376be |
i18n: add Brazilian Portuguese (pt-br) UI translation (#165)
* M14: translation catalogs, same system as PhotoCraft Move the interface translations to PhotoCraft's i18n system: one TSV catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro, entries keyed by command id, context or plural forms, and catalog tests (format, duplicates, placeholders, command ids). The 49 existing Japanese strings move over unchanged, plus "Auto". The language preference now defaults to "auto" and follows the system language (English when it has no catalog); "en" and "ja" still persist and unknown values are rejected. Update docs/localization.md, ROADMAP.md and the misc.prefs-language parity entry. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * i18n: add Brazilian Portuguese (pt-br) UI translation Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md. * M14: strict catalog validation, one-pass fmt, translation assets Fold in the infrastructure parts of #175: - `fmt` fills placeholders in one pass, so inserted values (a file name containing `{n}`) are never substituted again. - Catalog validation rejects unknown escapes, unknown `@` contexts, placeholder, ellipsis and plural-form mismatches and duplicates. The bundled catalogs must have no errors (tests); at run time a bad line is still only skipped and logged, so the rest of the catalog loads. - `.tsv` files count as assets in `cargo xtask assets`, with a `translation` kind that may never come from Adobe; ja.tsv gets its ATTRIBUTION.toml entry. - Control-channel test: switching the language keeps documents, their dirty state and command ids. Also make the drawing language thread-local, as in PhotoCraft, so parallel kittest harnesses can't change each other's language. Co-Authored-By: 才倾梦华V <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]> * M14: Brazilian Portuguese as a TSV catalog Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv (same 49 strings, plus Auto) and register it in LANGUAGES with PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and the docs and parity notes list the new code. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Simon Leblanc <[email protected]> Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> Co-authored-by: 才倾梦华V <[email protected]> |
||
|
|
a07243c8ff |
M14: translation catalogs, same system as PhotoCraft (#106)
* M14: translation catalogs, same system as PhotoCraft Move the interface translations to PhotoCraft's i18n system: one TSV catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro, entries keyed by command id, context or plural forms, and catalog tests (format, duplicates, placeholders, command ids). The 49 existing Japanese strings move over unchanged, plus "Auto". The language preference now defaults to "auto" and follows the system language (English when it has no catalog); "en" and "ja" still persist and unknown values are rejected. Update docs/localization.md, ROADMAP.md and the misc.prefs-language parity entry. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * M14: strict catalog validation, one-pass fmt, translation assets Fold in the infrastructure parts of #175: - `fmt` fills placeholders in one pass, so inserted values (a file name containing `{n}`) are never substituted again. - Catalog validation rejects unknown escapes, unknown `@` contexts, placeholder, ellipsis and plural-form mismatches and duplicates. The bundled catalogs must have no errors (tests); at run time a bad line is still only skipped and logged, so the rest of the catalog loads. - `.tsv` files count as assets in `cargo xtask assets`, with a `translation` kind that may never come from Adobe; ja.tsv gets its ATTRIBUTION.toml entry. - Control-channel test: switching the language keeps documents, their dirty state and command ids. Also make the drawing language thread-local, as in PhotoCraft, so parallel kittest harnesses can't change each other's language. Co-Authored-By: 才倾梦华V <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]> Co-authored-by: Brandon Thomas <[email protected]> Co-authored-by: 才倾梦华V <[email protected]> |
||
|
|
d3db99818f |
Rename PrintCraft to PdfCraft (#174)
The app, crates, binaries, bundle id, packaging, icons, screenshots and docs are now PdfCraft / pdfcraft (repo storytold/pdfcraft). On first launch the desktop app moves the PrintCraft settings and crash-recovery folders to the new name, and both apps read settings saved under the old storage key, so upgrades keep recent files, preferences and unsaved work. The signing test fixtures keep their PrintCraft subject names (they are binary). Co-authored-by: Claude Opus 5.5 <[email protected]> |
||
|
|
1d67833599 |
Fonts: use craft-fonts as an optional build input; move the Japanese fonts out
Shippori Mincho (and its OFL file) leaves assets/fonts/: the Japanese fonts now live in storytold/craft-fonts. printcraft-fonts gets craft-fonts' build.rs recipe: with CRAFT_FONTS_DIR=<checkout> it embeds the manifest's fonts as CRAFT_FONTS (wasm32: only BIZ UDPGothic Regular); without it CRAFT_FONTS is empty and the app builds, tests and runs as before, minus the Japanese face. - SHIPPORI_MINCHO is now Option<&[u8]> from CRAFT_FONTS; japanese_glyph (was shippori_glyph) uses document_japanese_font() (Shippori Mincho, then BIZ UDMincho, then any Jpan face) and returns GlyphError::NoFont without one. - Editing PDF text into Japanese without craft-fonts is a clear EditError that leaves the page untouched. - UI: every Jpan craft font (BIZ UDPGothic first) is the last fallback of every egui family, sharing the same static bytes. - Tests: Japanese glyph/edit tests skip without craft-fonts; new UI tests for no-tofu Japanese with craft-fonts and working fonts without it. - CI: the Linux test job checks out craft-fonts at a pinned SHA and runs the tests with CRAFT_FONTS_DIR. Releases build every platform with it (CRAFT_FONTS_REQUIRED=1) and ship each font's OFL as OFL-<family>.txt. - ATTRIBUTION.toml gains [[build_input]] (checked by xtask assets); NOTICE, AGENTS.md, CLAUDE.md, README and docs say fonts live in craft-fonts. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
e59c9a793e |
Fix text editing layout and preserve source PDF font styles (#36)
* Comments: a text box's rectangle follows its edited text Editing a text box (or typewriter or callout) rewrote /Contents but kept the old /Rect: the appearance clipped the new text to the old box and silently dropped lines that no longer fit, while shorter text left an oversized box. set_contents now re-measures the text with the same Helvetica widths as at creation and re-fits the box: the wrap width and top edge stay, the height fits the wrapped lines. A callout's leader line keeps its place and re-attaches to the moved box (that geometry moved from set_rect into a shared apply_text_box). A locked box keeps its text editable, so it re-fits too. Covered by annot tests (grow and shrink with nothing clipped, callout leader re-attach, locked box) and a comment_edit round trip through the automation tools; parity entries cite them. Co-Authored-By: GLM <[email protected]> * Polish edit text and images tool * feat(edit-text): select source font style * fix(edit-text): preserve detected PDF font styles * feat(edit-text): support Japanese replacements * fix(forms): escape non-ASCII format script strings * Forms: unwrap_or instead of map_or with identity (clippy map_or_identity) Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Brandon Thomas <[email protected]> Co-authored-by: GLM <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]> |
||
|
|
d20eef9d56 |
Licensing: standard LICENSE files, NOTICE, ArtCraft brand terms
Adopt the shared Crafting Apps licensing standard. LICENSE-MIT names "ArtCraft Team and the PrintCraft contributors"; LICENSE-APACHE matches the standard byte for byte; NOTICE gets the standard header and brand paragraph above the existing third-party list. docs/brand/LICENSE-brand.txt now holds the ArtCraft Team brand terms: the marks may be used only unmodified within PrintCraft, and forks and modified versions must remove them. The brand entries in ATTRIBUTION.toml, AGENTS.md §1.2 and the README follow suit, and the README's Licence section becomes the standard "License and credits" block. xtask inherits the workspace licence. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
6ff0bf8f64 |
M6: Merge data files into spreadsheet (FDF, XFDF, filled PDF forms → CSV); form_merge_data tool
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
06f8d73ec7 |
M6: Acrobat JavaScript: sandboxed boa engine with the forms object model (printcraft-js); custom keystroke/validate/calculate/format scripts, button scripts, document JavaScripts, JavaScript console (⌘J), Preferences ▸ Enable JavaScript; js_run, js_document_scripts, js_set_document_script, form_set_script, js_enabled tools
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
b87cf39168 |
M10: Scan & OCR ▸ Recognize text: ocrs-based recognition (models fetched by cargo xtask models), invisible searchable text layer, Recognize Text dialog with background progress; ocr_recognize / ocr_status tools
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
d7c22d7ef0 |
M7: Justify, underline, line spacing, character spacing and horizontal scale for existing paragraphs (and justify for added text); Lucide align-justify icon
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
01d0dc67ba |
M5: Fill & Sign typed signatures and initials (Type or Draw; script-font outlines drawn as filled paths); fill_sign_add signature/initials
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
1f2e267f32 |
app icon: lion (owner's ArtCraft drawing), Dock/taskbar/launcher wiring, palette docs
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
7515170103 |
M4: Cut, copy and paste pages in Organize Pages (⌘C/⌘X/⌘V and a thumbnail context menu; paste after the selection, across documents; the last page can't be cut)
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
e06a98adaa |
M9.1–M9.3: new sign crate: DER, X.509, CMS SignedData, PKCS #12 (PBES2 and legacy, MAC) on RustCrypto with aws-lc-rs for RSA private keys; PAdES B-B signing (new or existing field, visible or invisible, DocMDP certification) with an incremental placeholder save; validation (digest, signature, chain against a trust store, changes after signing classified under DocMDP); checked against pdfsig and OpenSSL
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
7616535dd1 |
M5: Polygon, Connected lines, Cloud (cloudy border appearance), Callout (leader line with arrow, /RD text box, resize re-attaches the leader) and Insert text (caret) comments: annot shapes and appearances, click-to-place-points and drag-to-callout tools in the Comment/Highlight/Draw flyouts, /IT carried to the comment list (Callout, Cloud labels), comment_add types polygon/cloud/polyline/callout/caret
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
098d9ed4e1 |
M7.5: Edit image for added images: rotate (the box turns around its centre), flip horizontal/vertical, crop each side (clipped), replace the picture keeping box and transforms; Edit panel tools, content_update rotate/flip/crop/image; pixel-checked rendering
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
92d37ca696 |
M6.6/M6.8: Field Properties Appearance tab (border/fill colour, thickness, solid/dashed/beveled/inset/underline, text colour, Helvetica/Times/Courier); tab order by rows/columns/structure (page /Tabs) honoured by Tab; push buttons run Reset form, Named (print, page navigation), URI, Go to and common one-line scripts (this.print, this.resetForm, app.alert, pageNum) without a JS engine; form_tab_order tool and appearance in form_set_props (67 tools)
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
57980200e2 |
M7.4: Edit a PDF ▸ Add content: text (click and type; standard fonts, size, bold/italic, colour, alignment, wrapping) and images (PNG/JPEG/TIFF/GIF/BMP, centred at natural size) as page content that stays editable: each item is its own tagged content stream with its parameters, drawn in display space; select, move, resize (images keep proportions), double-click to retype, Format text panel, Delete; Bates numbering ▸ Add opens Header & Footer with a Bates number. content_list/page_add_text/page_add_image/content_update/content_delete tools (66 tools). Lucide align-center/right icons
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
67ff9303c8 |
M6.1/M6.2: form filling: new fonts (L2) and forms (L3) crates; field tree with inheritance, widgets, options; set_value with validation and regenerated appearances (auto-size, comb, multiline, password, quadding, /MK, combo, list selection), check/radio states (own AP when missing), reset to /DV; engine SetFieldValue/ResetForm with fill-forms permission; UI in-place editor (Enter/click-away commit, Escape, Tab with select-all), check/radio toggle, choice popup, Clear form; tools form_fields/form_fill/form_reset. Perf: named destinations indexed once (190 MB manual opens in 1.8 s instead of 172 s); comment and form edits refresh view data from the object graph instead of a full re-inspection (6x faster per edit on large files; equivalence-tested). annot uses the shared fonts helpers. Docs, parity, roadmap.
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
54e288c5fe |
M5.3/M5.4: commenting UI: quick-bar Comment/Highlight/Draw flyout groups with pin, colour and thickness; sticky note and text box composer; highlight/underline/strikethrough from text selection; freehand, line, arrow, rectangle and oval gestures with live previews; Select tool selects (per-line frames for markup), moves, resizes with 8 handles, edits and deletes comments; canvas context menu (edit, reply, set status, colour, delete); Comments panel rewrite (add-a-comment box, search, selectable cards with reply box, ... menu, inline edit, status badges); comment edits re-render only their page and keep stale rasters on screen; control channel ui.drag, secondary click, pages_on_screen and comment state; view options quick/author/comment; 7 Lucide icons; parity entries; README
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
2fc7cb4e64 |
Community links: Discord button in the title bar, ArtCraft community card on Home, About dialog with ArtCraft mark/wordmark and links, Help menu commands (help.discord/app_page/github/website), CLI --version and MCP websiteUrl, README Community section; 4 Lucide icons (attributed); regenerated screenshots with honest brand attribution
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
bb31b5a1b5 |
Brand assets: ArtCraft logos attributed as Storyteller-owned (not open source, LicenseRef-Storyteller-Trademark) with a narrow asset-gate exception for docs/brand logos; AGENTS.md §1.2
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
0ac2908195 |
M4.6: bookmark editing: organize outline API (add/rename/move/delete/set page, surgical relinking, /Count recompute), undoable engine edits, 6 automation tools, Bookmarks panel (⌘B new + inline rename, context menu: rename, set page, move, indent/outdent, delete), Lucide bookmark-plus icon (attributed)
Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
5f5f83cc0c |
Session 4: M1.6 encryption (crypt crate R2-R6), M4 command registry, combine/extract/split, autosave + crash recovery, asset policy + xtask assets, README screenshots
Co-Authored-By: Claude Opus 5.5 <[email protected]> |