Pro edisi
Diff — Referensi Mendalam
Sekilas pandang
Bagian berjudul “Sekilas pandang”Halaman ini adalah referensi tingkat kontrak untuk modul diff NextPDF Pro, NextPDF\Pro\Diff. Modul ini membandingkan dua dokumen PDF dan melaporkan perubahan teks, gambar, dan metadata. PdfDiffer menghasilkan diff baris Myers yang selaras per halaman. StructuredDiffer menambahkan pengelompokan paragraf, perbandingan gambar, dan perbandingan metadata. DiffFormatter menserialisasi hasil terstruktur ke JSON atau fragmen HTML. Halaman ini menyatakan API publik, kontrak perilaku yang dapat diamati, batas sumber daya, dan mode kegagalan. Penyiapan berorientasi tugas dan contoh tersedia di halaman kapabilitas Diff.
Ketersediaan & lisensi
Bagian berjudul “Ketersediaan & lisensi”Kapabilitas ini hadir dalam NextPDF Pro (nextpdf/pro) dan aktif dengan envelope lisensi tingkat Pro. Deployment tanpa hak tersebut tidak memuat kelas-kelas kapabilitas ini. Bandingkan edisi dan dapatkan lisensi.
Tidak ada flag kapabilitas runtime yang menggerbang modul ini. Kelas-kelas diff dapat digunakan setiap kali nextpdf/pro terinstal dan berlisensi.
Permukaan API publik
Bagian berjudul “Permukaan API publik”| Simbol | Parameter | Perilaku default | Mengembalikan | Melempar atau gagal dengan | Catatan |
|---|---|---|---|---|---|
PdfDiffer::compare() | string $sourcePdf, string $targetPdf | Mengekstraksi teks per halaman, lalu men-diff halaman i sumber terhadap halaman i target | DiffResult | InvalidArgumentException ketika sebuah buffer tidak memiliki header %PDF atau pembaca opsional gagal mengurai; OverflowException pada batas sumber daya | Titik masuk statis |
PdfDiffer::compareTexts() | array $sourcePages, array $targetPages (list<string> masing-masing) | Men-diff teks halaman yang telah diekstraksi sebelumnya, melewati ekstraksi | DiffResult | OverflowException pada batas sumber daya | Statis; gunakan ketika teks sudah tersedia |
PdfDiffer::extractText() | string $contentStream | Mengurai operator penampil teks dari satu content stream mentah | string | — (toleran kesalahan; masukan yang tidak dapat diurai menghasilkan string kosong) | Statis |
StructuredDiffer::__construct() | ?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = null | Argumen null mengonstruksi differ default | — | — | Injeksi konstruktor untuk pengujian |
StructuredDiffer::compare() | string $sourcePdf, string $targetPdf | Menjalankan perbandingan teks, paragraf, gambar, dan metadata, lalu membangun ringkasan | StructuredDiffResult | Meneruskan InvalidArgumentException dan OverflowException dari jalur teks | Orkestrator atas seluruh modul |
DiffFormatter::toJson() | StructuredDiffResult $result | Dokumen JSON yang diformat rapi | string | JsonException ketika encoding gagal | — |
DiffFormatter::toHtml() | StructuredDiffResult $result | Fragmen HTML dengan bagian ringkasan, paragraf, dan metadata; nilai teks di-escape sebagai entitas | string | — | Hanya fragmen, bukan dokumen lengkap |
DiffFormatter::toArray() | StructuredDiffResult $result | Array serialisasi yang mendukung toJson() | array<string, mixed> | — | Kunci snake_case yang stabil |
ImageDiffer::diff() | string $sourcePdf, string $targetPdf | Meng-hash image XObject dan melaporkan gambar yang ditambahkan, dihapus, dan dimodifikasi | list<ImageDiff> | — (struktur yang tidak dapat didekode dilewati secara fail-closed) | Identitas adalah bucket halaman ditambah nomor objek |
MetadataDiffer::diff() | string $sourcePdf, string $targetPdf | Membandingkan delapan field /Info (Title, Author, Subject, Keywords, Creator, Producer, CreationDate, ModDate) | list<MetadataChange> | — (tidak pernah melempar pada masukan yang tidak sesuai) | Nilai dibandingkan sebagai string yang telah didekode |
DiffEngine::diff() | array $sourceLines, array $targetLines, int $pageIndex = 0, int $maxLines = 10000 | Diff baris Myers atas dua daftar baris | list<DiffRegion> | OverflowException ketika total baris melebihi $maxLines atau jarak edit melebihi batas terikat-memori | Statis; penghasil wilayah untuk semua jalur teks |
TextExtractor::fromContentStream() | string $contentStream | Menokenisasi stream dan menjalankan mesin keadaan teks | list<TextBlock> | — | Statis |
TextExtractor::fromOperations() | array $operations (list<ContentStreamOp>) | Menjalankan mesin keadaan teks atas operasi yang telah diurai sebelumnya | list<TextBlock> | — | Statis |
ContentStreamParser::parse() | konstruktor menerima string $data | Menokenisasi operator dan operan; melewati dictionary dan komentar; toleran kesalahan | list<ContentStreamOp> | — | Byte yang tidak dikenali dilewati, tidak pernah fatal |
ContentStreamOp | string $operator, list<mixed> $operands | Value object operasi readonly; isTextOp() mengklasifikasikan operator terkait teks | — | — | — |
DiffResult | list<DiffRegion> $regions, int $sourcePagesCount, int $targetPagesCount | Mengelompokkan wilayah ke $added, $removed, $modified; mengekspos isIdentical(), hasDifferences(), totalChanges() | — | — | Readonly; wilayah Unchanged hanya tetap berada di $regions |
StructuredDiffResult | diff teks, paragraf, gambar, perubahan metadata, ringkasan | Hasil agregat; hasDifferences(), isIdentical() mendelegasikan ke ringkasan | — | — | Readonly |
DiffSummary | jumlah per kategori ditambah jumlah halaman | hasDifferences() dan totalChanges() atas jumlah teks, gambar, dan metadata | — | — | Readonly |
DiffRegion | DiffType $type, string $text, int $pageIndex, int $lineIndex, ?string $counterpartText = null | Satu perubahan tingkat baris | — | — | $counterpartText tetap null pada mesin yang dirilis |
ParagraphDiff | tipe, teks, indeks halaman, baris awal/akhir, wilayah | Wilayah bertipe sama yang berurutan pada satu halaman; lineCount() | — | — | Readonly |
ImageDiff | tipe, indeks halaman, hash sumber, hash target, id objek | Satu entri perubahan gambar | — | — | Hash berupa string kosong pada sisi yang tidak ada |
MetadataChange | string $field, ?string $sourceValue, ?string $targetValue | Satu perubahan field; isAdded(), isRemoved(), isModified() | — | — | null berarti field tidak ada |
TextBlock | teks, x, y, nama font, ukuran font, indeks baris | Satu text run yang diekstraksi dengan posisi perkiraan | — | — | Readonly |
DiffType | enum: Added, Removed, Modified, Unchanged | Klasifikasi perubahan berbasis string untuk teks | — | — | Lihat catatan Modified di kontrak perilaku |
ImageDiffType | enum: Added, Removed, Modified, Unchanged | Klasifikasi perubahan berbasis string untuk gambar | — | — | — |
Tanda tangan titik masuk
Bagian berjudul “Tanda tangan titik masuk”public static function compare(string $sourcePdf, string $targetPdf): DiffResult
public static function compareTexts(array $sourcePages, array $targetPages): DiffResult
public static function extractText(string $contentStream): stringpublic function __construct( ?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = null,)
public function compare(string $sourcePdf, string $targetPdf): StructuredDiffResultpublic function toJson(StructuredDiffResult $result): string
public function toHtml(StructuredDiffResult $result): string
public function toArray(StructuredDiffResult $result): arraypublic static function diff( array $sourceLines, array $targetLines, int $pageIndex = 0, int $maxLines = self::MAX_DIFF_LINES,): arrayKontrak perilaku
Bagian berjudul “Kontrak perilaku”Penyelarasan halaman dan diff baris
Bagian berjudul “Penyelarasan halaman dan diff baris”PdfDiffer::compare() mengekstraksi teks per halaman, lalu men-diff halaman i sumber terhadap halaman i target. Ketika jumlah halaman berbeda, sisi yang hilang diperlakukan sebagai teks kosong untuk halaman yang berlebih. Dalam tiap pasangan halaman, teks dipecah pada baris baru dan diff baris Myers berjalan per halaman. Mesin memancarkan wilayah Added, Removed, dan Unchanged. Sebuah baris yang berubah muncul sebagai wilayah Removed ditambah Added; mesin yang dirilis tidak pernah memancarkan wilayah teks Modified. Kasus Modified dan bucket DiffResult::$modified melayani hasil yang dikonstruksi pemanggil, karena konstruktor DiffResult bersifat publik. totalChanges() menghitung wilayah added, removed, dan modified; wilayah unchanged dikecualikan.
Jalur ekstraksi
Bagian berjudul “Jalur ekstraksi”Ekstraksi memiliki dua jalur:
- Pembaca Artisan opsional hadir. Ketika kelas
NextPDF\Parser\PdfReaderopsional terinstal, content stream halaman dibaca melaluinya untuk teks yang akurat per halaman. Jumlah halaman pada trailer menggerakkan loop. Sebuah halaman yang gagal dibaca menyumbangkan teks kosong alih-alih membatalkan perbandingan. - Cadangan. Pemindai tingkat byte berbatas menemukan pasangan
stream/endstreamdenganstrpos, meng-inflate data FlateDecode dengan batas keluaran keras 50 MB, dan membalikkan filter prediktor PNG ketika stream dictionary memintanya melalui/DecodeParmssesuai ISO 32000-2:2020 §7.4.4.4. Prediktor yang cacat atau tidak didukung membiarkan byte terdekode tidak berubah. Cadangan menggabungkan semua teks yang dipulihkan ke dalam satu bucket halaman, sehingga penyelarasan tingkat halaman hanya akurat per halaman pada jalur pembaca.
Kedua jalur mengurai operator penampil teks §9.4 Tj, TJ, dan '. Mesin keadaan melacak BT/ET, Tm (hanya origin), Td/TD, T*, dan Tf.
Perbandingan terstruktur
Bagian berjudul “Perbandingan terstruktur”StructuredDiffer::compare() menjalankan diff teks, mengelompokkan wilayah bertipe sama yang berurutan pada halaman yang sama menjadi paragraf (termasuk run unchanged), lalu menjalankan perbandingan gambar dan metadata serta merangkai sebuah DiffSummary. Jumlah paragraf dalam ringkasan hanya mencakup paragraf added, removed, dan modified.
Perbandingan gambar mengenumerasi objek PDF secara struktural. Rentang badan sebuah stream diatur oleh entri /Length-nya sesuai §7.3.8.2, sehingga byte biner yang sekadar menyerupai sintaks objek tidak pernah terdaftar sebagai objek fantom. Object stream terkompresi (/Type /ObjStm) didekode sesuai §7.5.7 agar image XObject yang bersarang di dalamnya terlihat. Setiap gambar yang terdeteksi di-hash berdasarkan konten dengan fungsi non-kriptografis xxh128; identitasnya adalah pasangan bucket halaman dan nomor objek. Gambar tanpa halaman pemilik dalam urutan stream diatribusikan ke halaman 0.
Perbandingan metadata meresolusi dictionary /Info yang sebenarnya melalui trailer bila memungkinkan, sehingga token field umpan di dalam content stream tidak keliru dianggap sebagai metadata dokumen. Nilai field didekode sebagai string PDF: bentuk literal sesuai §7.3.4.2 dan bentuk heksadesimal sesuai §7.3.4.3. Tanpa trailer yang dapat diresolusi, pencarian jatuh kembali ke seluruh masukan. Tanggal dibandingkan sebagai string yang telah didekode, bukan timestamp yang telah diurai.
Keluaran laporan
Bagian berjudul “Keluaran laporan”DiffFormatter::toJson() mengembalikan JSON yang diformat rapi dan meng-encode dengan JSON_THROW_ON_ERROR, sehingga kegagalan encoding memunculkan JsonException alih-alih mengembalikan false. toHtml() mengembalikan fragmen <div class="nextpdf-diff">; teks paragraf dan nilai metadata melewati escaping entitas HTML. Tidak ada keluaran PDF redline berdampingan secara visual. Untuk masukan yang identik, wilayah dan keluaran terformat bersifat deterministik.
Kasus tepi & mode kegagalan
Bagian berjudul “Kasus tepi & mode kegagalan”- Penyelarasan halaman bersifat posisional. Satu halaman yang disisipkan atau dihapus menggeser penyelarasan untuk semua halaman berikutnya dan menggelembungkan jumlah perubahan di hilir.
- Pada jalur ekstraksi cadangan, semua teks mendarat di indeks halaman 0. Men-diff dokumen yang diekstraksi pembaca terhadap ekspektasi dari jalur cadangan menghasilkan atribusi halaman yang berbeda.
- Buffer sumber atau target yang tidak diawali
%PDFgagal denganInvalidArgumentExceptionsebelum perbandingan apa pun. - Lebih dari 10,000 total baris dalam satu pasangan halaman gagal dengan
OverflowException(batas jumlah baris). - Dua teks halaman yang berbagi terlalu sedikit baris gagal dengan
OverflowExceptionbegitu jarak edit Myers melebihi batas terikat-memori. Revisi yang sah berbagi sebagian besar baris dan tetap tidak terpengaruh; masukan adversarial dengan kesamaan rendah memicu batas tersebut. - Keluaran stream cadangan terdekompresi yang lebih besar dari 50 MB gagal dengan
OverflowException(batas decompression bomb). Pemindai menggunakanstrpos, bukan regex tak berbatas, sehingga masukan yang dirancang tidak dapat memicu backtracking katastrofik. - Operator penampil teks
"ditokenisasi tetapi tidak menghasilkan text block pada 3.1.0; teks yang hanya ditampilkan melalui"tidak berpartisipasi dalam diff. - PDF hasil pindaian yang hanya berisi gambar menghasilkan sedikit atau tanpa diff teks. Tidak ada OCR yang berjalan.
- Deteksi perubahan gambar bersifat struktural, bukan perseptual. Ia tidak me-rasterisasi halaman, dan sebuah gambar yang di-encode ulang dengan piksel identik dilaporkan sebagai modified ketika byte-nya berbeda.
- Sebuah gambar yang bucket halaman atau nomor objeknya berubah antar revisi dilaporkan sebagai pasangan removed-plus-added, bukan sebagai modified.
- Object stream yang terkompresi dengan filter selain FlateDecode dilewati secara fail-closed; gambar anggotanya tidak dibandingkan.
- Tidak ada operasi kriptografis yang terjadi di modul ini, sehingga tidak ada perilaku spesifik mode FIPS. Hash gambar hanya untuk deteksi perubahan dan tidak membawa bobot integritas atau pembuktian.
Kesesuaian
Bagian berjudul “Kesesuaian”| Klaim | Standar | Klausul |
|---|---|---|
Operator penampil teks Tj dan TJ diurai untuk ekstraksi | ISO 32000-2:2020 | §9.4 |
Data stream cadangan dimulai setelah CRLF atau LF yang mengikuti kata kunci stream | ISO 32000-2:2020 | §7.3.8.1 |
Rentang stream pemindaian gambar diatur oleh entri /Length pada dictionary | ISO 32000-2:2020 | §7.3.8.2 |
Anggota object stream ditemukan melalui tabel pasangan /N dan offset /First | ISO 32000-2:2020 | §7.5.7 |
Pembalikan prediktor PNG mengikuti parameter Predictor pada /DecodeParms | ISO 32000-2:2020 | §7.4.4.4 |
| Nilai metadata mendekode bentuk string literal dan heksadesimal | ISO 32000-2:2020 | §7.3.4.2, §7.3.4.3 |
| Keluaran PDF redline berdampingan secara visual | — | Tidak didukung (hanya JSON/HTML) |
Semua klausul diparafrasekan; NextPDF tidak mereproduksi teks normatif. Ini adalah pernyataan kapabilitas, bukan sertifikasi; NextPDF tidak memegang sertifikasi apa pun dan tidak memberikan sertifikasi apa pun. Pemulihan teks merekonstruksi teks baris dari operator penampil teks. Ia tidak menjalankan mesin keadaan teks §9.4 lengkap, sehingga diff berada di tingkat konten, bukan tingkat geometri.
Catatan pengembangan
Bagian berjudul “Catatan pengembangan”- Ketersediaan dalam paket Pro:
PdfDiffer,DiffEngine,TextExtractor, dan value object-nya sejak 1.8.0;StructuredDiffer,DiffFormatter,ImageDiffer,MetadataDiffer, dan value object-nya sejak 2.2.0. Semuanya terkini dinextpdf/pro3.1.0. - Utamakan
PdfDiffer::compareTexts()ketika teks halaman sudah tersedia; ia melewati ekstraksi dan mode kegagalannya sepenuhnya. - Pembaca Artisan opsional meningkatkan akurasi ekstraksi dan atribusi halaman. Ia dideteksi saat runtime dan tidak pernah diwajibkan.
- Tangkap
OverflowExceptionsaat men-diff masukan tak tepercaya; batas-batas tersebut adalah penolakan fail-closed yang disengaja, bukan kesalahan transien. DiffFormatter::toHtml()memancarkan nama kelas (diff-added,diff-removed,diff-modified,diff-unchanged) tetapi tanpa stylesheet; sediakan CSS Anda sendiri.- Konstruksi
StructuredDifferdengan differ stub dalam pengujian untuk mengisolasi jalur teks dari pemindaian gambar dan metadata.
Batas publikasi
Bagian berjudul “Batas publikasi”Halaman ini hanya mendokumentasikan perilaku yang dapat diamati secara eksternal dan permukaan API publik yang didukung. Jalur namespace internal, kelas helper, tabel mekanisme, nama file runbook, dan prefiks tiket berada di luar cakupan.
Lihat juga
Bagian berjudul “Lihat juga”- Diff (kapabilitas) — instalasi, mulai cepat, dan contoh produksi.
- Converter — Referensi Mendalam
- Filter — Referensi Mendalam