Pages paired by their content, not by their number, so inserting a cover page does not report the whole document as changed. Each changed page is compared by the text engine, marks and folding included.
Pages pair by content, not by index#
This is the decision the engine is built around. Insert a cover page and every page number after it shifts by one — so a comparison that paired page 4 against page 4 would report an entire document as rewritten when a single page was added at the front.
Instead, the two lists of page texts are aligned the way the text engine aligns lines, one level up: a sequence diff with a similarity comparator, so two pages count as the same page when they share more than half their words. A removal immediately followed by an addition is read as a rewritten page while both sides still have one; past that, whichever side ran out has the page missing.
The sample pair#
11-pdf/ is a three-page supply agreement against a four-page revision of it. The revision adds a cover page at the front, edits the delivery and payment terms, and turns the last page landscape:
| Before | After | State | Why |
|---|---|---|---|
| — | 1 | added | The new cover page |
| 1 | 2 | same | Definitions and Orders, untouched |
| 2 | 3 | changed | 30 days → 14 days, 30 days → 45 days, 4% → 8%, one new sentence |
| 3 | 4 | changed | The words are identical; the page was rotated |
Every page keeps its identity. Paired on number instead, all four rows would have read as changed.
Each changed page is a text diff#
The comparison inside a page is the text engine's, not a second implementation of one. So word-level marks, folded unchanged runs and the shared normalisation rules all work inside a page for free:
Metadata is its own table#
Title, Author, Producer and whatever else the document carries are compared as a table of their own, and only the fields that differ are listed. In the sample pair that is one field: the Title gains a v3 while the Author and Producer are unchanged.
Metadata comparison is an option and can be turned off, in which case no metadata rows appear at all.
Geometry: a resized page is a changed page#
A page whose size in points changed is reported even when its words did not. That is the last row of the sample pair: 595 × 842 became 842 × 595 — the same A4 page turned landscape — with identical text on it. A comparison that only looked at words would have called that page unchanged, which is not what a reader would say about it.
A page with no text says so#
A scan, or a page that is one large image, has nothing for a text comparison to read. Those pages are counted and named — reported as having no extractable text — rather than shown as identical, which is what an empty-against-empty comparison would otherwise produce.
The count is of page positions, not of pages: a position that is blank on both sides is one page in the comparison, not two.
Two honest limits#
A gotcha worth knowing about#
Limits#
| Limit | Value | What happens past it |
|---|---|---|
| Pages per side | 500 | Reading stops and the notes say so |
| Page similarity | 0.5 | Below it, two pages are a removal and an addition rather than one edited page |
The similarity floor is deliberately lower than the text engine's line threshold: a page holds far more words than a line, so two versions of the same page can differ a great deal and still obviously be the same page.
When a document cannot be read#
An encrypted or corrupt PDF is a real answer, not a crash. The error names the reason and offers Compare as files as a button — the binary engine can still say whether the two files are the same bytes, which is sometimes all you needed.
In the app#
| Control | What it does |
|---|---|
| Show | Changed pages · All (with a count) |
| Page-count chip | 3 → 4 pages, always visible |
| No-text chip | Appears only when some page has no extractable text |