Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
2805 commits
Select commit Hold shift + click to select a range
06b9054
refactor(ui-egui): split print_ui.rs into print_ui/
aiongg Oct 26, 2026
3cbfa25
refactor(ui-egui): split combine_grid.rs into combine_grid/
aiongg Oct 26, 2026
dee909c
refactor(ui-egui): split fill_sign.rs into fill_sign/
aiongg Oct 26, 2026
bcb9628
refactor(ui-egui): split editing.rs into editing/
aiongg Oct 26, 2026
925d9c1
test(ui-egui): list fill_sign/scan.rs among the page modules
aiongg Oct 26, 2026
208d24b
refactor(ui-egui): move autoscroll.rs into canvas/
aiongg Oct 26, 2026
715c5ec
refactor(ui-egui): move crop.rs into canvas/
aiongg Oct 26, 2026
3e69c3b
refactor(ui-egui): move fling.rs into canvas/
aiongg Oct 26, 2026
611efb2
refactor(ui-egui): move image_pick.rs into canvas/
aiongg Oct 26, 2026
fceda5b
refactor(ui-egui): move page_pointer.rs into canvas/
aiongg Oct 26, 2026
c558ee5
refactor(ui-egui): move scroll_speed.rs into canvas/
aiongg Oct 26, 2026
26f0a36
refactor(ui-egui): move signature_drag.rs into canvas/
aiongg Oct 26, 2026
8a72428
refactor(ui-egui): move wheel_boost.rs into canvas/
aiongg Oct 26, 2026
1f73801
refactor(ui-egui): move wheel_pager.rs into canvas/
aiongg Oct 26, 2026
b60c029
refactor(ui-egui): move zoom_snap.rs into canvas/
aiongg Oct 26, 2026
49f5e69
refactor(ui-egui): move bulk_fields.rs into tools/
aiongg Oct 26, 2026
0996ece
refactor(ui-egui): move calc_order_ui.rs into tools/
aiongg Oct 26, 2026
8563041
refactor(ui-egui): move camera_ui.rs into tools/
aiongg Oct 26, 2026
e4865e8
refactor(ui-egui): move comments.rs into tools/
aiongg Oct 26, 2026
fbbc4d6
refactor(ui-egui): move content_ui.rs into tools/
aiongg Oct 26, 2026
f35adcd
refactor(ui-egui): move edit_text_ui.rs into tools/
aiongg Oct 26, 2026
10b689f
refactor(ui-egui): move field_table_ui.rs into tools/
aiongg Oct 26, 2026
2f8712b
refactor(ui-egui): move fill_sign.rs into tools/
aiongg Oct 26, 2026
e012ef8
refactor(ui-egui): move forms_ui.rs into tools/
aiongg Oct 26, 2026
f8ee929
refactor(ui-egui): move link_ui.rs into tools/
aiongg Oct 26, 2026
3448ddf
refactor(ui-egui): move measure_ui.rs into tools/
aiongg Oct 26, 2026
c8ef7f6
refactor(ui-egui): move object_ui.rs into tools/
aiongg Oct 26, 2026
67c2038
refactor(ui-egui): move prepare.rs into tools/
aiongg Oct 26, 2026
5d66a1a
refactor(ui-egui): move redact_ui.rs into tools/
aiongg Oct 26, 2026
d055e7e
refactor(ui-egui): move sign_ui.rs into tools/
aiongg Oct 26, 2026
e74c807
refactor(ui-egui): move stamps_ui.rs into tools/
aiongg Oct 26, 2026
fc4a75d
refactor(ui-egui): move tags_ui.rs into tools/
aiongg Oct 26, 2026
6e85f0d
refactor(ui-egui): move a11y_ui.rs into workflows/
aiongg Oct 26, 2026
e23e460
refactor(ui-egui): move actions_ui.rs into workflows/
aiongg Oct 26, 2026
46010b6
refactor(ui-egui): move combine_grid.rs into workflows/
aiongg Oct 26, 2026
6607eb5
refactor(ui-egui): move combine_ui.rs into workflows/
aiongg Oct 26, 2026
5c36be9
refactor(ui-egui): move compare_ui.rs into workflows/
aiongg Oct 26, 2026
c0740b6
refactor(ui-egui): move create_multiple_ui.rs into workflows/
aiongg Oct 26, 2026
a1babcd
refactor(ui-egui): move create_ui.rs into workflows/
aiongg Oct 26, 2026
ce98222
refactor(ui-egui): move export_ui.rs into workflows/
aiongg Oct 26, 2026
beb8b9c
refactor(ui-egui): move files.rs into workflows/
aiongg Oct 26, 2026
94a71db
refactor(ui-egui): move js_ui.rs into workflows/
aiongg Oct 26, 2026
c1024e0
refactor(ui-egui): move ocr_ui.rs into workflows/
aiongg Oct 26, 2026
37578f2
refactor(ui-egui): move optimize_ui.rs into workflows/
aiongg Oct 26, 2026
9254db5
refactor(ui-egui): move print_ui.rs into workflows/
aiongg Oct 26, 2026
c5d4982
refactor(ui-egui): move web_print.rs into workflows/
aiongg Oct 26, 2026
40bb91b
refactor(ui-egui): move appearance.rs into dialogs/
aiongg Oct 26, 2026
385e24e
refactor(ui-egui): move comment_props.rs into dialogs/
aiongg Oct 26, 2026
f877aaf
refactor(ui-egui): move credits.rs into dialogs/
aiongg Oct 26, 2026
e901fb8
refactor(ui-egui): move marks_ui.rs into dialogs/
aiongg Oct 26, 2026
7f0799c
refactor(ui-egui): move pageboxes.rs into dialogs/
aiongg Oct 26, 2026
e080461
refactor(ui-egui): move palette.rs into dialogs/
aiongg Oct 26, 2026
de0e370
refactor(ui-egui): move protect.rs into dialogs/
aiongg Oct 26, 2026
1096b2a
refactor(ui-egui): move standards_ui.rs into dialogs/
aiongg Oct 26, 2026
900d56c
refactor(ui-egui): move word_count_ui.rs into dialogs/
aiongg Oct 26, 2026
81e489b
refactor(ui-egui): move all_tools_ui.rs into panels/
aiongg Oct 26, 2026
604ad52
refactor(ui-egui): move comments_panel.rs into panels/
aiongg Oct 26, 2026
9771123
refactor(ui-egui): move format_text_ui.rs into panels/
aiongg Oct 26, 2026
946767d
refactor(ui-egui): move organize_panel.rs into panels/
aiongg Oct 26, 2026
dc6b6a5
refactor(ui-egui): move page_selection_ui.rs into panels/
aiongg Oct 26, 2026
9c27b33
refactor(ui-egui): move search_ui.rs into panels/
aiongg Oct 26, 2026
963b25f
refactor(ui-egui): move side_panels.rs into panels/
aiongg Oct 26, 2026
228a91c
refactor(ui-egui): move icon_data.rs into widgets/
aiongg Oct 26, 2026
73cd1b1
refactor(ui-egui): move icons.rs into widgets/
aiongg Oct 26, 2026
3e7cc6e
refactor(ui-egui): move drag_pointer.rs into platform/
aiongg Oct 26, 2026
d15c5a2
refactor(ui-egui): move file_watch.rs into platform/
aiongg Oct 26, 2026
0e559fc
fix(ui-egui): the field editor sizes auto-size text as the page does
Oct 26, 2026
9a9813b
Merge pull request #4880 from storytold/fix/nextest-0.9.150
skylartaylor Oct 26, 2026
0457aa8
fix(redact): Q inside a text object restores the text matrices; rever…
Oct 26, 2026
ad33ab6
fix(render): a non-isolated knockout group blends its elements with t…
Oct 27, 2026
6638646
refactor(ui-egui): move macos_association.rs into platform/
aiongg Oct 26, 2026
d3cfadd
refactor(ui-egui): move motion.rs into platform/
aiongg Oct 26, 2026
16b4977
refactor(ui-egui): move open_worker.rs into platform/
aiongg Oct 26, 2026
b37c3a9
refactor(ui-egui): move pickers.rs into platform/
aiongg Oct 26, 2026
2b4f769
refactor(ui-egui): move portable.rs into platform/
aiongg Oct 26, 2026
dc97e74
refactor(ui-egui): move ui_scale.rs into platform/
aiongg Oct 26, 2026
90a1880
refactor(ui-egui): move updates.rs into platform/
aiongg Oct 26, 2026
687f6f6
refactor(ui-egui): move window_controls.rs into platform/
aiongg Oct 26, 2026
5527f93
refactor(ui-egui): move last_session.rs into persist/
aiongg Oct 26, 2026
615232d
refactor(ui-egui): move last_view.rs into persist/
aiongg Oct 26, 2026
dc25a6e
refactor(ui-egui): move recovery.rs into persist/
aiongg Oct 26, 2026
d25378c
refactor(ui-egui): move units.rs into persist/
aiongg Oct 26, 2026
ed09547
refactor(ui-egui): move window_state.rs into persist/
aiongg Oct 26, 2026
80c4572
refactor(ui-egui): move system_fonts.rs into platform/
aiongg Oct 26, 2026
7b3d688
test(ui-egui): rerun the fontconfig tests by their platform:: path
aiongg Oct 26, 2026
cd0fc37
refactor(ui-egui): move folders_ui.rs into home/
aiongg Oct 26, 2026
636656a
refactor(ui-egui): move tab_context.rs into menus/
aiongg Oct 26, 2026
cb94c8f
refactor(ui-egui): move open_worker_tests.rs to platform/open_worker/…
aiongg Oct 26, 2026
3dbea4e
docs(parity): point evidence at the ui-egui files' new directories
aiongg Oct 26, 2026
064632e
test(ui-egui): name the page modules by their new directories
aiongg Oct 26, 2026
d449f2c
docs: name the ui-egui files by their new directories
aiongg Oct 26, 2026
323172e
test(automation): end the file access scan at the test module, not at…
aiongg Oct 26, 2026
f022ef0
style: cargo fmt on moved files
aiongg Oct 26, 2026
1dd2737
Merge pull request #4889 from aiongg/layout
aiongg Oct 27, 2026
cef9908
Merge origin/main into fix/auto-size-follows-field-height
Oct 27, 2026
dffe6dd
fix(edit, a11y): Q inside a text object restores the text matrices, a…
Oct 27, 2026
3c6612a
fix(forms-ui): measure auto-size text at no more than the screen-font…
Oct 27, 2026
a7b07bf
fix(render): a stroke whose outline comes back with NaN is drawn, not…
Oct 27, 2026
f595a96
Merge remote-tracking branch 'upstream/main' into fix/delete-one-radi…
claude Oct 27, 2026
38c9482
fix(xfa, create): read a BMP's pixels from after its headers when its…
Oct 27, 2026
de9ab53
fix(xfa): leave a 16-byte BMP header to the decoder; test core header…
Oct 27, 2026
fd8c8c1
fix(xfa): repair a BMP offset that points at the header's end with ma…
Oct 27, 2026
32df177
feat(installer): default to a per-user ArtCraft folder
Jeremy8776 Oct 26, 2026
c39a0f3
fix(installer): address scope and ARM64 review feedback
Jeremy8776 Oct 27, 2026
c1670d0
fix(installer): keep the desktop shortcut on a machine-wide update; h…
Jeremy8776 Oct 27, 2026
a9ddf79
M6: a radio button renamed to a radio group's name joins that group (…
Oct 27, 2026
315e7fa
docs(installer): describe the per-user default install location and s…
Jeremy8776 Oct 27, 2026
27a0cd6
M6: joining radio buttons that share an export value keep sharing it
Oct 27, 2026
f386165
Merge remote-tracking branch 'upstream/main' into fix/cropbox-text-cl…
jonathanwxh-cell Oct 27, 2026
c56a4b3
docs(installer): note that the 32-bit all-users folder is Program Fil…
Jeremy8776 Oct 27, 2026
2c054ab
M6: a radio group with an indirect /Kids keeps its buttons when joined
Oct 27, 2026
0ea9a23
M6: editing or sorting a list's items keeps its selected indices on i…
Oct 27, 2026
ee6f2a0
fix(ui): enforce copy permission before reading bookmark styles
Lcoding15 Oct 27, 2026
67ecccf
fix(ui): reuse translated copy-permission message
Lcoding15 Oct 27, 2026
3ed4f23
M6: a list box's top row follows its options when they change
Oct 27, 2026
d39fe5b
M6: clearing a field's default leaves it with none, not its parent fi…
Oct 27, 2026
12c9051
M6: clearing a field's value leaves it empty, not its parent field's
Oct 27, 2026
7a61777
M6: each list box widget with its own top row scrolls by itself
Oct 27, 2026
4580e5c
fix(installer): resolve the wizard scope and folder correctly
Jeremy8776 Oct 27, 2026
5abf32e
fix(render): knockout passes clear a masked image's coverage, and not…
Oct 27, 2026
ea8b729
M6: a joined radio button stays selected, keeps its actions, and alwa…
Oct 27, 2026
58c50f6
M6: a list box's top row is chosen after the edit's new font size
Oct 27, 2026
37bf4ee
perf(engine): export page images on worker threads
Silvertree2010 Oct 27, 2026
b8871e8
M6: a joining button that was its own field keeps only its widget tri…
Oct 27, 2026
6a76d28
fix(render): a shading in a knockout group replaces only what is unde…
Oct 27, 2026
e9fc890
Merge pull request #5026 from Silvertree2010/perf/export-speed
aiongg Oct 27, 2026
da8cea2
M10: reuse verified OCR model and packaging prerequisites
KyleKassen Oct 27, 2026
bf353cb
fix(installer): check the exact architecture-specific machine folder
Jeremy8776 Oct 27, 2026
1889690
Merge pull request #5039 from Jeremy8776/fix/ocr-model-onnx-urls
aiongg Oct 27, 2026
9e90b2a
refactor(ui): use craft-ui's ComboBox for every dropdown (#4988)
aiongg Oct 27, 2026
65d8385
Merge remote-tracking branch 'upstream/main' into feat/bookmarks-from…
claude Oct 27, 2026
0cd6a19
M6: a radio button without its /Parent link leaves its group's /Kids too
claude Oct 27, 2026
e895573
Merge storytold/pdfcraft main
Oct 27, 2026
dfb74c7
ci: use storytold/craft-common-actions windows-arm64 workflow
Oct 27, 2026
cace97e
M4: one text style can't be given to two bookmark levels
claude Oct 27, 2026
5af1027
Merge pull request #4892 from Jeremy8776/feat/install-scope-policy
aiongg Oct 27, 2026
d915af5
Merge remote-tracking branch 'upstream/main' into feat/bookmarks-from…
claude Oct 27, 2026
7f33b11
M4: the text-style level lists are craft-ui combo boxes
claude Oct 27, 2026
7d1ed99
Refactor annot for strict Clippy checks
dylanmtaylor Oct 27, 2026
9d97546
Refactor automation for strict Clippy checks
dylanmtaylor Oct 27, 2026
84c873d
Refactor cos for strict Clippy checks
dylanmtaylor Oct 27, 2026
de73c35
Refactor edit for strict Clippy checks
dylanmtaylor Oct 27, 2026
166f706
Refactor engine for strict Clippy checks
dylanmtaylor Oct 27, 2026
5e75b9c
Refactor export for strict Clippy checks
dylanmtaylor Oct 27, 2026
4965e23
Refactor forms for strict Clippy checks
dylanmtaylor Oct 27, 2026
a059881
Refactor js for strict Clippy checks
dylanmtaylor Oct 27, 2026
f40a578
Refactor organize for strict Clippy checks
dylanmtaylor Oct 27, 2026
530e2a2
Refactor pdfcraft-cli for strict Clippy checks
dylanmtaylor Oct 27, 2026
c043c82
Refactor preflight for strict Clippy checks
dylanmtaylor Oct 27, 2026
bc89733
Refactor print for strict Clippy checks
dylanmtaylor Oct 27, 2026
33e23da
Refactor redact for strict Clippy checks
dylanmtaylor Oct 27, 2026
a119095
Refactor render for strict Clippy checks
dylanmtaylor Oct 27, 2026
074d4f3
Refactor sign for strict Clippy checks
dylanmtaylor Oct 27, 2026
e7a60f2
Refactor ui canvas for strict Clippy checks
dylanmtaylor Oct 27, 2026
f796c71
Refactor ui commands for strict Clippy checks
dylanmtaylor Oct 27, 2026
bf89bf9
Refactor ui dialogs for strict Clippy checks
dylanmtaylor Oct 27, 2026
2d27306
Refactor ui support for strict Clippy checks
dylanmtaylor Oct 27, 2026
21cae66
Refactor ui tools for strict Clippy checks
dylanmtaylor Oct 27, 2026
2ca9275
Refactor ui workflows for strict Clippy checks
dylanmtaylor Oct 27, 2026
9530dbb
Refactor xfa for strict Clippy checks
dylanmtaylor Oct 27, 2026
92bc2f9
Refactor xfdf for strict Clippy checks
dylanmtaylor Oct 27, 2026
d95ff38
Enforce workspace Clippy standards and document lint policy
dylanmtaylor Oct 27, 2026
63bc58a
Fix menu overflow and form pointer handling
dylanmtaylor Oct 27, 2026
81c63c0
Group annotation, form and document operation parameters
dylanmtaylor Oct 27, 2026
5fecdb9
Group signing and timestamp validation inputs
dylanmtaylor Oct 27, 2026
775d6a4
Group demo form field properties
dylanmtaylor Oct 27, 2026
31833c9
Group UI interaction and rendering parameters
dylanmtaylor Oct 27, 2026
76ce895
Restore translated security and shortcut labels
dylanmtaylor Oct 27, 2026
ef894ae
Fix platform-gated imports for Windows and wasm builds
dylanmtaylor Oct 28, 2026
ad95afb
Qualify signing calls for macOS and Windows builds
dylanmtaylor Oct 28, 2026
e496635
Restore the preflight check flow and the overflow menu title
dylanmtaylor Oct 28, 2026
3932ee0
Enforce Rust coding standards via Clippy (#4897)
dylanmtaylor Oct 28, 2026
68e78e7
Merge origin/main into fix/choice-index-follows-options
Oct 28, 2026
47909b0
Merge origin/main into fix/text-matrix-survives-q
Oct 28, 2026
d95ea87
Merge origin/main into fix/cleared-default-stays-cleared
Oct 28, 2026
969cad0
Merge origin/main into fix/radio-join-group-by-name
Oct 28, 2026
20eebc1
deps: pin craft-libs at e11f9d9a so Cargo before 1.99 loads craft-men…
aiongg Oct 28, 2026
6e0eec6
C011: sorting keeps which of two items with one export value is selected
Oct 28, 2026
5716a95
C010: joining a group redraws only the buttons that moved
Oct 28, 2026
ac40f62
C012 test: a cleared choice kid has no selected value, exactly
Oct 28, 2026
03fdf97
Merge remote-tracking branch 'upstream/main' into feat/bookmarks-from…
claude Oct 28, 2026
fc010ef
Merge remote-tracking branch 'upstream/main' into fix/cropbox-text-cl…
jonathanwxh-cell Oct 28, 2026
b3cbb77
Merge origin/main into fix/marks-update-preview-without-old-marks
alehel Oct 28, 2026
871a3e1
Merge origin/main into fix/page-cursor-writer
alehel Oct 28, 2026
c14910b
docs(ui): a link's tip shows where a press acts on it, with Select or…
alehel Oct 28, 2026
1e01497
fix(ui): Update prepares the unmarked pages once, and shows the thumb…
alehel Oct 28, 2026
098a1f8
fix(ui): Update draws the page shown without its marks at once, and a…
alehel Oct 28, 2026
dcec1ce
fix(ui): Update's preview parses its unmarked copy once and keeps a p…
alehel Oct 28, 2026
1e239b0
fix(ui): a page that fails to render ahead isn't asked again every frame
alehel Oct 28, 2026
aad8a38
M7: Type1 fonts with an OpenType-wrapped CFF program draw their own face
Oct 28, 2026
45d95f1
macOS packaging: retry stapler when Apple's CloudKit drops the connec…
Oct 28, 2026
75360d1
Release 0.15.0
Oct 28, 2026
4628237
M7: the missing-CFF fallback test checks it draws the stand-in
Oct 28, 2026
67d4f18
Grant network access so update checks can reach GitHub (#5189)
dylanmtaylor Oct 28, 2026
05630b5
fix(render): a gray drawn with the Color blend mode is no longer draw…
Oct 28, 2026
11d9b4c
test(render): don't claim which vello_cpu pipeline the Luminosity gua…
Oct 28, 2026
7555be3
Honor CARGO_BUILD_TARGET in FreeBSD packaging for aarch64 release bui…
dylanmtaylor Oct 28, 2026
750012c
Merge pull request #2402 from wstock/fix/2368-flatten-no-rotate
aiongg Oct 28, 2026
40c22e3
Export Data as CSV keeps formula-like cells as text, like the merge r…
oracola91 Oct 28, 2026
03996b1
Improve reading-colour preferences and add a settings shortcut (#2627)
sampaiodias Oct 28, 2026
31f5182
Merge pull request #2838 from jonathanwxh-cell/fix/cropbox-text-clipping
aiongg Oct 28, 2026
21f6c29
M6: form script messages keep their title, icon and buttons, and ever…
EricKaden Oct 28, 2026
8f3a4f1
M6: Organize pages ▸ Page properties sets the selected pages' tab ord…
dotCooCoo Oct 28, 2026
4d8dc3a
Merge pull request #4560 from Lcoding15/feat/bookmarks-from-text-styles
aiongg Oct 28, 2026
222a124
M5: Import comments takes another PDF and copies its comments onto th…
dotCooCoo Oct 28, 2026
f824475
Merge pull request #4631 from Lcoding15/fix/delete-one-radio-button
aiongg Oct 28, 2026
7cde655
Merge pull request #4709 from alehel/fix/page-cursor-writer
aiongg Oct 28, 2026
dc943ee
Merge pull request #4718 from alehel/fix/marks-update-preview-without…
aiongg Oct 28, 2026
ba09e1a
fix(render): an isolated DeviceCMYK transparency group blends in CMYK
jpeskov Oct 21, 2026
7f9530d
fix(render): an ICCBased CMYK colour is not taken as process tints; f…
jpeskov Oct 21, 2026
f4fe2d9
fix(render): blend large CMYK groups in every tile; decline nested is…
jpeskov Oct 21, 2026
d1f5658
chore(vendor): renumber the CMYK-group patches after rebasing onto main
Oct 28, 2026
4127784
fix(vendor): keep draw_isolated_cmyk_group's doc comment on that func…
Oct 28, 2026
6fcfb3f
fix(render): an isolated CMYK group inside a knockout element is eras…
Oct 28, 2026
2a26479
Merge origin/main into fix/radio-join-group-by-name
Oct 28, 2026
304f27f
Merge origin/main into fix/choice-index-follows-options
Oct 28, 2026
3aeafeb
Merge origin/main into fix/cleared-default-stays-cleared
Oct 28, 2026
e518e27
Merge #5199 (fix/color-blend-gray-black) so the CMYK K ink pass blend…
Oct 29, 2026
367f7d5
fix(render): a pattern before an isolated CMYK group no longer moves it
Oct 29, 2026
2e6f7e5
Integrate KenM76 PR #4831
FredApps Oct 29, 2026
f716bd1
Integrate KenM76 PR #4841
FredApps Oct 29, 2026
a66686c
Integrate KenM76 PR #4862
FredApps Oct 29, 2026
b0555cb
Integrate KenM76 PR #4898
FredApps Oct 29, 2026
d9ddd8a
Integrate KenM76 PR #4906
FredApps Oct 29, 2026
ebd7578
Integrate KenM76 PR #4913
FredApps Oct 29, 2026
d1fcc12
Integrate KenM76 PR #4943
FredApps Oct 29, 2026
9e30913
Integrate KenM76 PR #4977
FredApps Oct 29, 2026
07edd05
Integrate KenM76 PR #4987
FredApps Oct 29, 2026
e34cb1d
Integrate KenM76 PR #4991
FredApps Oct 29, 2026
1b0e3b6
Integrate KenM76 PR #5178
FredApps Oct 29, 2026
7fc2033
Integrate KenM76 PR #5199
FredApps Oct 29, 2026
f280f3a
Integrate KenM76 PR #5228
FredApps Oct 29, 2026
97c062a
Complete additive integration fields and test boundaries
FredApps Oct 29, 2026
d995381
Clarify integrated vendor regression coverage
FredApps Oct 29, 2026
3109bb2
Merge pull request #5236 from FredApps/integration/kenm76-2026-10-29
aiongg Oct 29, 2026
c735fb7
Make PdfCraft's app color red (#5245)
dylanmtaylor Oct 29, 2026
726ecf2
packaging: Flatpak finds and prints to CUPS printers (#5346)
dylanmtaylor Oct 29, 2026
834a4da
CI: workflows only call craft-common-actions at @main (#5378)
dylanmtaylor Oct 30, 2026
f76dbb9
deps: bump tar, zip, roxmltree, rustls-webpki and symphonia to their …
dylanmtaylor Oct 30, 2026
3517d05
Update prompt shows the app icon and accent color instead of a letter…
dylanmtaylor Oct 30, 2026
1d1cbc4
UPD.1: honor app pretend versions in update checks (#5397)
dylanmtaylor Oct 30, 2026
ee0ef67
Merge upstream pdfcraft into PlutarchPages
ryanduguid Oct 30, 2026
339f742
Adopt the full Mermaid palette across the app, icon and screenshots
ryanduguid Oct 30, 2026
bce2f81
Refuse shared annotation appearances and keep overlays readable
ryanduguid Oct 30, 2026
2f23f62
Keep on-page outlines readable on white pages in the dark theme
ryanduguid Oct 30, 2026
45a25a9
Keep the installer's folder record under the PlutarchPages registry key
ryanduguid Oct 30, 2026
d5f2ca8
Pin the shared CI workflows and pass SonarCloud only its token
ryanduguid Oct 30, 2026
84a817e
Expect this fork's manufacturer in the MSI check
ryanduguid Oct 30, 2026
0c1fd7d
Name PlutarchPages on the installer's context-menu checkbox
ryanduguid Oct 30, 2026
df956ed
Exclude tests and vendored crates from CodeQL
ryanduguid Oct 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
reviews:
auto_review:
# Dependabot bumps are checked by CI; skip CodeRabbit reviews on them.
ignore_usernames:
- "dependabot[bot]"
3 changes: 3 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Minimum cargo-nextest for this repository: GHSA-vc25-qg58-w57c is fixed in 0.9.150 and CI
# installs exactly that version, so an older nextest refuses to run (exit 92 REQUIRED_VERSION_NOT_MET).
nextest-version = "0.9.150"
2 changes: 1 addition & 1 deletion .github/assets/badges/rust.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions .github/codeql/codeql-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Tests hold known passwords and crypto vectors on purpose. Vendored crates are patched copies of
# third-party code, whose PDF encryption code flags the formats' own constants. Excluding them keeps
# real findings in the app's code visible, but CodeQL no longer looks for bugs in these folders.
paths-ignore:
- "vendor/**"
- "xtask/**"
- "**/tests/**"
- "**/tests.rs"
- "**/*_tests.rs"
- "**/benches/**"
- "**/examples/**"
- "**/fuzz/**"
32 changes: 32 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: 2
updates:
# Maintain Rust / Cargo dependencies
- package-ecosystem: "cargo"
directories:
- "/"
- "/crates/filters/fuzz"
schedule:
interval: "daily"
time: "06:00"
timezone: "America/New_York"
# Consolidate updates into a single PR rather than one PR per crate
groups:
cargo-dependencies:
patterns:
- "*"
commit-message:
prefix: "chore(deps)"

# Maintain GitHub Actions workflows
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
time: "06:00"
timezone: "America/New_York"
groups:
actions:
patterns:
- "*"
commit-message:
prefix: "ci(deps)"
76 changes: 76 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<!--
Thanks for contributing to PdfCraft.

Base this on `main` — it is the only integration branch. `main` moves fast (it took
396 commits in the three days to 2026-10-12), so a PR that sits for a day usually needs
a rebase. Rebasing the same day you are asked keeps the work from dying of conflicts.
Delete any section below that does not apply.
-->

## What this changes

<!-- What behaviour is different afterwards, and why it is worth doing. If it fixes an
issue, say `Fixes #123`. -->

## How you verified it

<!-- The commands you ran and what they said. Per-crate is fine and preferred:
`cargo test -p <crate>`. CI runs the full workspace on every PR, so you do not
need to locally. -->

- [ ] `cargo fmt --check`
- [ ] clippy with `-D warnings` on the crates I changed
- [ ] tests pass on the crates I changed
- [ ] `cargo xtask layers` and `cargo xtask assets` (if you touched crate boundaries or any asset)

**Tests.** New behaviour needs a test at the right scale — a property test, a unit test, a
crate integration test or an end-to-end one. For a bug fix, **please check that the test
fails before your fix** by reverting the fix and watching it go red. A test nobody has seen
fail is not evidence that it pins anything.

## Never-crash

Every PDF, script, MCP call, settings file and keystroke is untrusted input (`AGENTS.md` §4).

- [ ] No new `unwrap`/`expect`/`panic!`/`unreachable!`/`todo!` outside tests, unless it is
provably infallible with a comment saying why
- [ ] No indexing or slicing with input-derived positions (`get`, and strings only at char
boundaries); checked or saturating arithmetic; allocations sized by input are capped;
recursion is bounded
- [ ] No `unsafe`
- [ ] Any crash this fixes has a small synthetic regression test

## Provenance

This is the part that cannot be undone after a merge, and the part a new contributor is
least likely to know about. Please read `AGENTS.md` §1 before adding any asset.

- [ ] No asset from an Adobe product, and no Adobe icon recreated, traced or imitated
- [ ] No font files committed here (they live in
[storytold/craft-fonts](https://github.com/storytold/craft-fonts))
- [ ] No GPL/AGPL code copied in — MuPDF, Ghostscript, Poppler, veraPDF and DSS may only be
run as external oracle processes
- [ ] Behaviour comes from the specification or black-box observation, **not** from reading
another implementation's source
- [ ] Every new asset has an `ATTRIBUTION.toml` entry and `cargo xtask assets` passes

## Security

- [ ] `--root` confinement still holds on every path, including ones reached by nested
tool dispatch
- [ ] MCP and the UI control channel stay opt-in, loopback-only and token-authenticated
- [ ] No new outbound network access (that decision is the owner's)

## Parity and reach

- [ ] `parity/acrobat-features.toml` updated in this PR, with `notes` saying what is *still*
missing — `shipped` means "exists and tested", not "as good as Acrobat"
- [ ] Reachable headlessly through an `automation` tool where that applies (`AGENTS.md` §3),
so agents can drive it and not just the UI
- [ ] Docs updated if this changes a documented behaviour (`docs/`, crate README)

## Anything a reviewer should look at first

<!-- The judgement call you are least sure about, a deliberate restraint you want pinned,
or a behaviour change existing users will notice. Say so here rather than leaving it
to be found. -->
195 changes: 77 additions & 118 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,133 +1,92 @@
name: CI

# Quality gates for every push to main and every pull request (`cargo xtask ci`), through the
# suite's shared gate workflow in craft-common-actions. Nightly fuzzing is in fuzz.yml.
on:
push:
branches: [main]
pull_request:
# `labeled` so that adding `full-ci` to an open PR starts a run with Windows in it.
types: [opened, synchronize, reopened, labeled]
workflow_dispatch:
schedule:
- cron: "17 3 * * *" # nightly fuzzing

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
# The token is only used to check out the code: no job writes to the repository.
permissions:
contents: read

# A newer push to a PR branch cancels its older run; every push to main runs to the end. Adding
# any label but `full-ci` gets a group of its own, so it neither runs the gate nor cancels a run.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
group: ci-${{ github.event_name == 'pull_request' && (github.event.action != 'labeled' || github.event.label.name == 'full-ci') && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
test:
name: test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# No macOS on PRs, main or nightly: the org's 5 macOS slots are kept for release builds,
# and release.yml builds macOS (a failing release is fixed and rebuilt).
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4

# The optional craft-fonts build input (Japanese fonts), so the Japanese font tests run on
# Linux; Windows tests the build without it. See craftrules standards/fonts.md.
- name: Check out craft-fonts (Linux)
if: runner.os == 'Linux'
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
repository: storytold/craft-fonts
ref: 8dcdacd5153e64560d109541a47d806f26f048c0
path: craft-fonts

- name: Install Linux system dependencies (egui/winit/rfd)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libxkbcommon-dev libwayland-dev libx11-dev libxrandr-dev libxi-dev \
libgl1-mesa-dev libgtk-3-dev

- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt

- name: Require Windows executable resources
if: runner.os == 'Windows'
run: Add-Content -Path $env:GITHUB_ENV -Value 'PDFCRAFT_REQUIRE_WINRES=1'
shell: pwsh

- uses: Swatinem/rust-cache@v2

- name: Format
if: runner.os == 'Linux'
run: cargo fmt --all -- --check

- name: Clippy
run: cargo clippy --workspace --all-targets -- -D warnings

- name: Test
if: runner.os != 'Linux'
run: cargo test --workspace

- name: Test (with craft-fonts)
if: runner.os == 'Linux'
env:
CRAFT_FONTS_DIR: ${{ github.workspace }}/craft-fonts
CRAFT_FONTS_REQUIRED: "1"
run: cargo test --workspace

- name: Layering
run: cargo xtask layers

- name: Assets (licences and attribution)
if: runner.os == 'Linux'
run: cargo xtask assets

- name: CLI without the MCP server still builds
if: runner.os == 'Linux'
run: cargo check -p pdfcraft-cli --no-default-features

wasm:
name: wasm32 check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:
key: wasm32
- name: Check library crates for wasm32
run: cargo xtask wasm

deny:
name: dependency licences and advisories
# The shared gate doesn't check where git dependencies come from; release.yml runs the same job.
git-sources:
if: github.event.action != 'labeled' || github.event.label.name == 'full-ci'
name: Git dependencies come from storytold
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
command: check

fuzz:
name: fuzz (mutation, 15 min)
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: fuzz
- name: Fetch the pdf.js corpus (seeds)
run: cargo xtask corpus
- name: Fuzz
run: cargo xtask fuzz --time 900 --seed ${{ github.run_number }}
- name: Upload findings
if: always()
uses: actions/upload-artifact@v4
with:
name: fuzz-findings
path: fuzz-out/findings
if-no-files-found: ignore
persist-credentials: false
- name: Windows font notice regressions
shell: pwsh
run: ./packaging/windows/test-font-notices.ps1
- name: Git dependencies come from storytold
run: |
set -euo pipefail
test -f Cargo.lock || { echo "Cargo.lock is missing"; exit 1; }
# Source replacement, patches and path overrides in cargo config never show up
# in Cargo.lock. Parsed rather than grepped: TOML has many spellings of one key.
# Cargo still reads the legacy .cargo/config.
python3 - <<'PY'
import os, sys, tomllib
for path in (".cargo/config", ".cargo/config.toml"):
if not os.path.exists(path):
continue
config = tomllib.load(open(path, "rb"))
replaced = [name for name, source in config.get("source", {}).items()
if isinstance(source, dict) and "replace-with" in source]
if replaced or "patch" in config or "paths" in config:
print(f"{path} replaces, patches or overrides a source")
sys.exit(1)
PY
# Fails when Cargo.lock is out of date with the manifests.
cargo metadata --locked --format-version 1 > /dev/null
python3 - <<'PY'
import sys, tomllib
lock = tomllib.load(open("Cargo.lock", "rb"))
bad = sorted({p["source"] for p in lock.get("package", [])
if p.get("source", "").startswith("git+")
and not p["source"].startswith("git+https://github.com/storytold/")})
if bad:
print("Git dependencies outside github.com/storytold:", *bad, sep="\n")
sys.exit(1)
PY

gate:
if: github.event.action != 'labeled' || github.event.label.name == 'full-ci'
# Pinned: a mutable reference to another repository can change what CI runs. Move it deliberately.
uses: storytold/craft-common-actions/.github/workflows/gate.yml@2b3fb9dc05036f73c77d18f753a3aa9da55fa386 # main, 31 October 2026
with:
# Windows on main, manual runs and pull requests labelled `full-ci`. No macOS on PRs or main:
# the org's 5 macOS slots are kept for release builds, and release.yml builds macOS.
os: ${{ (github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'full-ci')) && '["ubuntu-24.04","windows-latest"]' || '["ubuntu-24.04"]' }}
# Same craft-fonts commit as release.yml and freebsd.yml.
craft-fonts-ref: b076417b5880bd4154bd22f00695b1d28c6bea83
# egui/winit/rfd, and the independent oracles (crates/oracle).
packages: >-
libxkbcommon-dev libwayland-dev libx11-dev libxrandr-dev libxi-dev libgl1-mesa-dev
libgtk-3-dev qpdf poppler-utils
# cargo-deny for the deny step of `cargo xtask ci`, which requires it under CI.
tools: cargo-nextest@0.9.150,cargo-deny@0.20.2
# A missing oracle fails the job instead of printing a skip notice that reads as a pass.
linux-env: PDFCRAFT_ORACLES_REQUIRED=1
windows-env: PDFCRAFT_REQUIRE_WINRES=1
# Windows checks what differs by platform: the build (with resources) and the tests.
windows-command: |
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --workspace --locked
1 change: 1 addition & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
with:
languages: ${{ matrix.language }}
build-mode: none
config-file: ./.github/codeql/codeql-config.yml

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4
Expand Down
31 changes: 4 additions & 27 deletions .github/workflows/freebsd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,7 @@ permissions:

jobs:
freebsd:
name: FreeBSD 14 (build + test)
runs-on: ubuntu-latest
timeout-minutes: 300
steps:
- uses: actions/checkout@v4
- name: Build and test in a FreeBSD VM
uses: vmactions/freebsd-vm@c46abacb49f09938ca4e1702d15d836285d694cc # v1
with:
release: "14.3"
usesh: true
cpu: 4
mem: 12288
# Nothing to bring back; copying the target dir out of the VM fails on large builds.
copyback: false
prepare: |
pkg install -y bash git curl pkgconf cmake python3 libxkbcommon wayland libX11 libXcursor libXrandr libXi libxcb mesa-libs vulkan-loader gtk3 fontconfig freetype2 alsa-lib
curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal
run: |
. "$HOME/.cargo/env"
# The checkout is synced in under another owner; let tests that call git read it.
git config --global --add safe.directory "*"
rustc --version
CARGO_PROFILE_DEV_DEBUG=0 cargo build --workspace --all-targets --locked
CARGO_PROFILE_DEV_DEBUG=0 cargo test --workspace --locked
# The release packaging, end to end (a quicker release profile than the real release).
CARGO_PROFILE_RELEASE_LTO=false CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16 packaging/freebsd/package.sh
tar -tzf dist/release/pdfcraft-*-freebsd-*.tar.gz | grep -E '/bin/pdfcraft$|/bin/pdfcraft-cli$|applications/|/share/pdfcraft/models/.+\.onnx$'
# Pinned: a mutable reference to another repository can change what CI runs. Move it deliberately.
uses: storytold/craft-common-actions/.github/workflows/freebsd.yml@2b3fb9dc05036f73c77d18f753a3aa9da55fa386 # main, 31 October 2026
with:
craft-fonts-ref: b076417b5880bd4154bd22f00695b1d28c6bea83
Loading
Loading