You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
operations::reorder currently creates a new Document and converts each parsed page before saving. This can preserve page content and resources, but it does not preserve the complete original object graph. Reordering pages must not silently discard or rewrite unrelated document data such as annotations, outlines, named destinations, AcroForm references, structure trees, attachments, or metadata.
A page-order change should be written as an incremental revision, retaining the original indirect objects and bytes wherever possible. Objects that define the page tree may be replaced in the new revision when required to keep /Kids, /Count, /Parent, and inherited page attributes coherent. Unsupported inputs must return an explicit error instead of producing a degraded document.
This issue is phase 1 of the work and deliberately supports only unencrypted, unsigned documents. Certification-signature permission enforcement is tracked separately in #532.
The order must be an exact permutation of every source-page index: identical length, no duplicates, no omissions, and no out-of-range values. Separate extraction or duplication APIs can cover subsets and repeated pages.
Phase 1 expected behaviour
Preserve the original file bytes and append the page-order change as an incremental revision.
Preserve the original indirect page-object identifiers.
Preserve all unrelated indirect objects and catalog references.
Replace only the catalog/page-tree/page dictionaries required to maintain a valid tree.
Keep /Kids, /Count, and every page's /Parent mutually consistent.
Preserve the effective values of inherited page attributes when pages move between /Pages nodes, materializing inherited values when necessary.
Support page trees with multiple nested /Pages nodes.
Accept source files using classic xref tables, xref streams, or object streams; emit an incremental xref section compatible with the source.
Write to a temporary file in the destination directory and replace the destination atomically only after parsing and validation succeed.
Reopen and validate the completed output before replacing the destination.
“Lossless” in this API means that page contents, object identities, unrelated objects, and prior bytes are retained. It does not mean that page-tree dictionaries remain byte-for-byte unchanged: the new incremental revision must replace the minimum set of structural dictionaries needed for a valid reordered page tree.
Validation and failure behaviour
Reject an empty order unless the source document itself has zero pages.
Reject duplicate, omitted, and out-of-range page indices.
Reject malformed, cyclic, or unsupported page trees.
Never leave a partial destination file or corrupt an existing destination.
Tests
Add integration fixtures covering:
flat and nested page trees;
pages that inherit /Resources, /MediaBox, /CropBox, and /Rotate from different ancestors;
annotations and AcroForm widgets;
outlines and named destinations;
tagged PDFs and structure-tree references;
attachments and metadata;
classic xref tables and xref streams;
objects originally stored in object streams;
documents with existing incremental revisions;
malformed permutations and page trees;
explicit rejection of encrypted and signed documents;
atomic destination replacement on success and preservation of the previous destination on failure.
Verify that the requested page order is the only semantic change, every source page retains its indirect object identifier, unrelated objects remain reachable, inherited page behaviour is unchanged, and all pre-existing bytes remain as the prefix of the output.
Rebuilding every page through the high-level Document writer. This cannot guarantee preservation of the complete source object graph and can silently alter unrelated content.
Problem / use case
operations::reordercurrently creates a newDocumentand converts each parsed page before saving. This can preserve page content and resources, but it does not preserve the complete original object graph. Reordering pages must not silently discard or rewrite unrelated document data such as annotations, outlines, named destinations, AcroForm references, structure trees, attachments, or metadata.A page-order change should be written as an incremental revision, retaining the original indirect objects and bytes wherever possible. Objects that define the page tree may be replaced in the new revision when required to keep
/Kids,/Count,/Parent, and inherited page attributes coherent. Unsupported inputs must return an explicit error instead of producing a degraded document.This issue is phase 1 of the work and deliberately supports only unencrypted, unsigned documents. Certification-signature permission enforcement is tracked separately in #532.
Proposed API
The order must be an exact permutation of every source-page index: identical length, no duplicates, no omissions, and no out-of-range values. Separate extraction or duplication APIs can cover subsets and repeated pages.
Phase 1 expected behaviour
/Kids,/Count, and every page's/Parentmutually consistent./Pagesnodes, materializing inherited values when necessary./Pagesnodes.“Lossless” in this API means that page contents, object identities, unrelated objects, and prior bytes are retained. It does not mean that page-tree dictionaries remain byte-for-byte unchanged: the new incremental revision must replace the minimum set of structural dictionaries needed for a valid reordered page tree.
Validation and failure behaviour
Tests
Add integration fixtures covering:
/Resources,/MediaBox,/CropBox, and/Rotatefrom different ancestors;Verify that the requested page order is the only semantic change, every source page retains its indirect object identifier, unrelated objects remain reachable, inherited page behaviour is unchanged, and all pre-existing bytes remain as the prefix of the output.
Relevant bindings
Core only.
Follow-up
Alternatives considered
Rebuilding every page through the high-level
Documentwriter. This cannot guarantee preservation of the complete source object graph and can silently alter unrelated content.