* M8: redact lists of words or phrases Find text and redact gains "Multiple words or phrases": a list with one word or phrase per line, typed or imported from a .txt file (Import list…), whose every match is marked in one undo step. Lists are trimmed, deduplicated and bounded (1,000 entries of 256 characters; files up to 1 MB are read). redact_mark takes words and reports matched_words, the marks each entry made. protect.redact-word-lists is shipped; whole-word and case-sensitive matching and exporting the list are still missing. * M8: translate word-list labels into Arabic The Arabic catalog arrived on main after this branch, so the new Find text and redact strings were still English and failed arabic_covers_ui_literals. * Tests: drop sharp grid renders when the thumbnail will cover the cell Zooming the organize grid back out left the sharp page raster in place until a thumbnail texture existed, so the zoom test failed when that texture had not arrived yet. * M8: Czech rows for the word-list redaction labels Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
pdfcraft-redact
Layer L4 (may use edit): redaction, architecture §11.2.
// Marks are Redact annotations (pdfcraft-annot: Shape::Redact { quads, overlay }).
let marks: Vec<Mark> = marks(&doc); // page, areas (user space), fill, overlay text
let report = apply(&mut doc, None)?; // everything, or Some(&[pages])
clear_marks(&mut doc, None)?; // remove marks without applying
apply removes, under every marked area:
- text: glyphs are cut out of
Tj/TJ/'/"and replaced by aTJdisplacement of the same advance, so the rest of the line keeps its exact position. Widths come from/Widths,/W//DW(composite fonts, embedded CMaps with codespace and CID ranges), Type 3 font matrices, and approximations for the standard 14. A glyph goes when it overlaps an area by more than a fifth of its size (or a point) both ways; zero-size text goes when its origin is inside; - images: fully covered → removed; partly covered → a copy with the covered pixels cleared (8/16-bit and 1/2/4-bit images, image masks; Flate/LZW/RL/A85/AHx). Codecs PdfCraft can't re-encode (DCT, JPX, JBIG2, CCITT) are removed whole (fail-closed); inline images under an area are removed;
- vectors: covered paths are removed; partly covered paths and shadings are clipped so nothing paints inside the areas;
- form XObjects: rewritten recursively into new objects (pages sharing the original keep it);
- annotations whose rectangle overlaps (with their pop-ups), and form fields with a widget under a mark;
- the marks themselves, replaced by boxes in their fill colour (and overlay text) drawn into the
page as a
/PCMark /Redactionstream.
A verification pass re-reads each redacted page and fails the operation if any glyph or inline image is still under an area. Content that can't be decoded makes the operation fail rather than leave it unredacted.
Remove hidden information / Sanitize
let found = sanitize::scan(&doc); // [(Hidden, count)] per category
sanitize::remove_hidden(&mut doc, &[Hidden::Comments])?; // chosen categories
sanitize::sanitize(&mut doc)?; // all of them
Categories: metadata (/Info, XMP), file attachments, comments, form fields (flattened so the
values stay visible), hidden text (render modes 3 and 7, or wholly off the page), hidden layers
(content of off optional-content groups, then the groups), bookmarks, links/actions/JavaScript,
and /PieceInfo private data. Both make the next save a full rewrite.
patterns finds phone numbers, e-mail addresses, credit card numbers (Luhn-checked), US Social
Security numbers and dates for Search & Redact.
codes holds the redaction code sets (U.S. FOIA and U.S. Privacy Act exemptions):
CodeSet::from_id("foia")?.overlay(&["(b)(6)"]) gives the overlay text for the picked codes.
Custom code sets aren't supported yet.
Not yet: pattern locales, struct-tree/alt-text cleanup, metadata and hidden-information sanitising (M8.4), re-encoding of DCT images (they are removed instead).