Pro editie
Diff
In het kort
Sectie met titel “In het kort”NextPDF\Pro\Diff vergelijkt twee PDF-documenten en rapporteert wat er is gewijzigd. Het
snelle pad produceert een pagina-uitgelijnde tekst-diff; het gestructureerde pad voegt
detectie van wijzigingen in afbeeldingen en metadata toe en maakt het resultaat op als JSON of HTML.
Beschikbaarheid en licentie
Sectie met titel “Beschikbaarheid en licentie”Deze functie zit in NextPDF Pro (nextpdf/pro) en activeert met een
licentie-envelop op Pro-niveau. Een deployment zonder die entitlement laadt de klassen van de functie niet. Vergelijk edities en
vraag een licentie aan.
Geen runtime-mogelijkheidsvlag bewaakt de Diff-klassen; ze zijn aanwezig zodra het Pro-pakket is geïnstalleerd.
Installatie
Sectie met titel “Installatie”composer require nextpdf/pro:^3Conceptueel overzicht
Sectie met titel “Conceptueel overzicht”PdfDiffer::compare() extraheert per pagina tekst uit elk document, splitst deze
op in regels en voert per paginapaar een Myers-regel-diff uit, wat toegevoegde,
verwijderde en gewijzigde regio’s oplevert. Tekstextractie parseert de tekstweergave-
operatoren van ISO 32000-2:2020 §9.4 (Tj, TJ, ').
StructuredDiffer bouwt daarop voort: deze groepeert tekstregio’s tot wijzigingen op
alinea-niveau, vergelijkt ingebedde afbeeldingen, vergelijkt metadata en produceert een
StructuredDiffResult met een geaggregeerde samenvatting. DiffFormatter serialiseert
dat resultaat naar een JSON-string of een HTML-rapportfragment.
Wanneer de optionele Artisan PDF-reader is geïnstalleerd, gebruikt tekstextractie deze voor pagina-nauwkeurige inhoud; anders scant een begrensde fallback op byteniveau contentstreams rechtstreeks.
Waarom het zo werkt
Sectie met titel “Waarom het zo werkt”De differ vergelijkt geëxtraheerde tekst en structuur, niet gerenderde pixels. Een
structurele vergelijking is deterministisch, goedkoop en sluit aan op de redactionele
wijzigingen waar een beoordelaar om geeft. Een pixel-diff zou daarentegen antialiasing
en font-hinting-ruis als inhoud markeren. Omdat een PDF glyphs en positionering opslaat,
en niet kant-en-klare leesbare tekens, reconstrueert elke vergelijking eerst tekst uit de
contentstream. Die extractiestap is waarom de Artisan-reader de nauwkeurigheid aanscherpt,
waarom de begrensde FlateDecode-fallback dekking inruilt voor veiligheid, en
waarom gescande pagina’s nauwelijks diffen. Pagina-uitlijning blijft op index gebaseerd voor
voorspelbaarheid, zodat een ingevoegde pagina leest als een duidelijke stroomafwaartse verschuiving.
Ontwerpachtergrond: Waarom de tekst in een PDF niet echt tekst is.
Gedragscontract
Sectie met titel “Gedragscontract”- Invoer. Ruwe PDF-bytes voor bron en doel. Een buffer die niet begint met
%PDFwerptInvalidArgumentException. - Uitvoer (snelle pad).
DiffResultmet de regiolijstenadded,removed,modifiedplusisIdentical(),hasDifferences(),totalChanges(). - Uitvoer (gestructureerde pad).
StructuredDiffResultmet alinea-diffs, afbeeldings-diffs, metadatawijzigingen en eenDiffSummary. - Rapportuitvoer.
DiffFormatterzendt een JSON-string of een HTML-fragment uit. Deze produceert geen visuele zij-aan-zij-redline-PDF. - Resourcegrenzen. De gedecomprimeerde contentstreamgrootte is begrensd ter bescherming tegen decompressiebommen; de scanner op byteniveau vermijdt catastrofale regex-backtracking op geprepareerde invoer.
- Determinisme. Voor identieke invoer zijn de diff-regio’s en de opgemaakte uitvoer stabiel.
Publiek API-oppervlak
Sectie met titel “Publiek API-oppervlak”| Type | Soort | Belangrijkste leden |
|---|---|---|
NextPDF\Pro\Diff\PdfDiffer | final class | static compare(string $sourcePdf, string $targetPdf): DiffResult, static compareTexts(array $sourcePages, array $targetPages): DiffResult, static extractText(string $contentStream): string |
NextPDF\Pro\Diff\StructuredDiffer | final class | __construct(?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = null), compare(string $sourcePdf, string $targetPdf): StructuredDiffResult |
NextPDF\Pro\Diff\DiffFormatter | final class | toJson(StructuredDiffResult $result): string, toHtml(StructuredDiffResult $result): string |
NextPDF\Pro\Diff\DiffResult | final readonly class | array $added, array $removed, array $modified, isIdentical(): bool, hasDifferences(): bool, totalChanges(): int |
NextPDF\Pro\Diff\StructuredDiffResult | final readonly class | tekst-diff, alinea’s, afbeeldingen, metadatawijzigingen, samenvatting |
NextPDF\Pro\Diff\DiffType | enum | Added, Removed, Modified, Unchanged |
Codevoorbeeld — Snelstart
Sectie met titel “Codevoorbeeld — Snelstart”<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\PdfDiffer;
$diff = PdfDiffer::compare( file_get_contents('v1.pdf'), file_get_contents('v2.pdf'),);
if ($diff->hasDifferences()) { echo $diff->totalChanges(), " text changes detected\n";}Codevoorbeeld — Productie
Sectie met titel “Codevoorbeeld — Productie”<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\DiffFormatter;use NextPDF\Pro\Diff\StructuredDiffer;
function reviewReport(string $oldPdf, string $newPdf): string{ $result = (new StructuredDiffer())->compare($oldPdf, $newPdf);
// JSON for machine consumption; toHtml() for a review UI fragment. return (new DiffFormatter())->toJson($result);}Randgevallen en valkuilen
Sectie met titel “Randgevallen en valkuilen”- De diff is pagina-uitgelijnd op index. Een pagina vroeg invoegen verschuift alle latere pagina’s en rapporteert grote stroomafwaartse wijzigingen — dit is verwacht voor een index-uitgelijnde vergelijking.
- Afbeeldingsvergelijking detecteert toegevoegde, verwijderde en gewijzigde ingebedde afbeeldingen; het is geen perceptuele visuele diff en rendert geen pagina’s pixel voor pixel.
- Gescande alleen-afbeelding-PDF’s produceren weinig of geen tekst-diff omdat er geen OCR wordt uitgevoerd.
- Zonder de optionele Artisan-reader gebruikt extractie de begrensde fallback; sterk gecomprimeerde documenten kunnen een verminderde tekstdekking opleveren.
Prestaties
Sectie met titel “Prestaties”Tekstextractie is lineair in de documentbytes; de Myers-diff is
bijna-lineair voor vergelijkbare documenten en kwadratisch in het slechtste geval per pagina-
paar. De decompressielimiet begrenst het geheugen. Zie performance_budget.
Beveiligingsnotities
Sectie met titel “Beveiligingsnotities”De fallback op byteniveau gebruikt strpos-gebaseerd scannen in plaats van onbegrensde
regex om catastrofale backtracking op geprepareerde PDF’s te vermijden, en begrenst de
decompressie-uitvoer. Diffen voert geen ingebedde scripts uit. Zie het
Core-beveiligingsmodel.
Conformiteit
Sectie met titel “Conformiteit”| Claim | Spec-clausule | Status |
|---|---|---|
Tj-tekstoperator geparseerd voor extractie | ISO 32000-2:2020 §9.4 | Geverifieerd (unit suite) |
TJ-array-tekstoperator geparseerd voor extractie | ISO 32000-2:2020 §9.4 | Geverifieerd (unit suite) |
| Visuele zij-aan-zij-redline-PDF-uitvoer | — | Niet ondersteund (alleen JSON/HTML) |
Core-fallback / alternatief
Sectie met titel “Core-fallback / alternatief”Er bestaat geen Core-equivalent voor documentvergelijking. De optionele Artisan- reader verbetert de extractienauwkeurigheid wanneer geïnstalleerd, maar is niet vereist.
Enterprise-grensnotitie
Sectie met titel “Enterprise-grensnotitie”Dit is een detector van inhoudswijzigingen. Het is geen forensische verschilanalysator en produceert geen bewijskrachtige of manipulatieattributierapporten; die aangelegenheden vallen buiten het bereik van deze module.
Publicatiegrens
Sectie met titel “Publicatiegrens”Deze pagina documenteert alleen extern waarneembaar gedrag en het ondersteunde publieke API-oppervlak. Interne namespace-paden, helper-klassen, mechanismetabellen, runbook-bestandsnamen en ticketprefixen vallen buiten het bereik.