@adnsistemas/pdf-lib 2.4.5 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +43 -0
  2. package/cjs/api/PDFDocument.d.ts +14 -0
  3. package/cjs/api/PDFDocument.d.ts.map +1 -1
  4. package/cjs/api/PDFDocument.js +51 -3
  5. package/cjs/api/PDFDocument.js.map +1 -1
  6. package/cjs/api/PDFDocumentOptions.d.ts +1 -0
  7. package/cjs/api/PDFDocumentOptions.d.ts.map +1 -1
  8. package/cjs/api/snapshot/DefaultDocumentSnapshot.d.ts +4 -0
  9. package/cjs/api/snapshot/DefaultDocumentSnapshot.d.ts.map +1 -1
  10. package/cjs/api/snapshot/DefaultDocumentSnapshot.js +10 -0
  11. package/cjs/api/snapshot/DefaultDocumentSnapshot.js.map +1 -1
  12. package/cjs/api/snapshot/DocumentSnapshot.d.ts +4 -0
  13. package/cjs/api/snapshot/DocumentSnapshot.d.ts.map +1 -1
  14. package/cjs/api/snapshot/IncrementalDocumentSnapshot.d.ts +5 -0
  15. package/cjs/api/snapshot/IncrementalDocumentSnapshot.d.ts.map +1 -1
  16. package/cjs/api/snapshot/IncrementalDocumentSnapshot.js +17 -0
  17. package/cjs/api/snapshot/IncrementalDocumentSnapshot.js.map +1 -1
  18. package/cjs/core/PDFContext.d.ts +10 -1
  19. package/cjs/core/PDFContext.d.ts.map +1 -1
  20. package/cjs/core/PDFContext.js +52 -2
  21. package/cjs/core/PDFContext.js.map +1 -1
  22. package/cjs/core/document/PDFCrossRefSection.d.ts +6 -1
  23. package/cjs/core/document/PDFCrossRefSection.d.ts.map +1 -1
  24. package/cjs/core/document/PDFCrossRefSection.js +65 -2
  25. package/cjs/core/document/PDFCrossRefSection.js.map +1 -1
  26. package/cjs/core/parser/PDFParser.d.ts +2 -2
  27. package/cjs/core/parser/PDFParser.d.ts.map +1 -1
  28. package/cjs/core/parser/PDFParser.js +23 -5
  29. package/cjs/core/parser/PDFParser.js.map +1 -1
  30. package/cjs/core/parser/PDFXRefStreamParser.d.ts.map +1 -1
  31. package/cjs/core/parser/PDFXRefStreamParser.js +6 -0
  32. package/cjs/core/parser/PDFXRefStreamParser.js.map +1 -1
  33. package/cjs/core/writers/PDFWriter.d.ts.map +1 -1
  34. package/cjs/core/writers/PDFWriter.js +10 -0
  35. package/cjs/core/writers/PDFWriter.js.map +1 -1
  36. package/dist/pdf-lib.esm.js +232 -12
  37. package/dist/pdf-lib.esm.js.map +1 -1
  38. package/dist/pdf-lib.esm.min.js +3 -3
  39. package/dist/pdf-lib.esm.min.js.map +1 -1
  40. package/dist/pdf-lib.js +232 -12
  41. package/dist/pdf-lib.js.map +1 -1
  42. package/dist/pdf-lib.min.js +3 -3
  43. package/dist/pdf-lib.min.js.map +1 -1
  44. package/es/api/PDFDocument.d.ts +14 -0
  45. package/es/api/PDFDocument.d.ts.map +1 -1
  46. package/es/api/PDFDocument.js +51 -3
  47. package/es/api/PDFDocument.js.map +1 -1
  48. package/es/api/PDFDocumentOptions.d.ts +1 -0
  49. package/es/api/PDFDocumentOptions.d.ts.map +1 -1
  50. package/es/api/snapshot/DefaultDocumentSnapshot.d.ts +4 -0
  51. package/es/api/snapshot/DefaultDocumentSnapshot.d.ts.map +1 -1
  52. package/es/api/snapshot/DefaultDocumentSnapshot.js +10 -0
  53. package/es/api/snapshot/DefaultDocumentSnapshot.js.map +1 -1
  54. package/es/api/snapshot/DocumentSnapshot.d.ts +4 -0
  55. package/es/api/snapshot/DocumentSnapshot.d.ts.map +1 -1
  56. package/es/api/snapshot/IncrementalDocumentSnapshot.d.ts +5 -0
  57. package/es/api/snapshot/IncrementalDocumentSnapshot.d.ts.map +1 -1
  58. package/es/api/snapshot/IncrementalDocumentSnapshot.js +17 -0
  59. package/es/api/snapshot/IncrementalDocumentSnapshot.js.map +1 -1
  60. package/es/core/PDFContext.d.ts +10 -1
  61. package/es/core/PDFContext.d.ts.map +1 -1
  62. package/es/core/PDFContext.js +52 -2
  63. package/es/core/PDFContext.js.map +1 -1
  64. package/es/core/document/PDFCrossRefSection.d.ts +6 -1
  65. package/es/core/document/PDFCrossRefSection.d.ts.map +1 -1
  66. package/es/core/document/PDFCrossRefSection.js +65 -2
  67. package/es/core/document/PDFCrossRefSection.js.map +1 -1
  68. package/es/core/parser/PDFParser.d.ts +2 -2
  69. package/es/core/parser/PDFParser.d.ts.map +1 -1
  70. package/es/core/parser/PDFParser.js +23 -5
  71. package/es/core/parser/PDFParser.js.map +1 -1
  72. package/es/core/parser/PDFXRefStreamParser.d.ts.map +1 -1
  73. package/es/core/parser/PDFXRefStreamParser.js +6 -0
  74. package/es/core/parser/PDFXRefStreamParser.js.map +1 -1
  75. package/es/core/writers/PDFWriter.d.ts.map +1 -1
  76. package/es/core/writers/PDFWriter.js +10 -0
  77. package/es/core/writers/PDFWriter.js.map +1 -1
  78. package/package.json +4 -4
  79. package/src/api/PDFDocument.ts +55 -0
  80. package/src/api/PDFDocumentOptions.ts +1 -0
  81. package/src/api/snapshot/DefaultDocumentSnapshot.ts +13 -0
  82. package/src/api/snapshot/DocumentSnapshot.ts +6 -0
  83. package/src/api/snapshot/IncrementalDocumentSnapshot.ts +20 -0
  84. package/src/core/PDFContext.ts +53 -2
  85. package/src/core/document/PDFCrossRefSection.ts +70 -2
  86. package/src/core/parser/PDFParser.ts +22 -3
  87. package/src/core/parser/PDFXRefStreamParser.ts +8 -0
  88. package/src/core/writers/PDFWriter.ts +11 -0
  89. package/ts3.4/cjs/api/PDFDocument.d.ts +14 -0
  90. package/ts3.4/cjs/api/PDFDocumentOptions.d.ts +1 -0
  91. package/ts3.4/cjs/api/snapshot/DefaultDocumentSnapshot.d.ts +4 -0
  92. package/ts3.4/cjs/api/snapshot/DocumentSnapshot.d.ts +4 -0
  93. package/ts3.4/cjs/api/snapshot/IncrementalDocumentSnapshot.d.ts +5 -0
  94. package/ts3.4/cjs/core/PDFContext.d.ts +10 -1
  95. package/ts3.4/cjs/core/document/PDFCrossRefSection.d.ts +6 -1
  96. package/ts3.4/cjs/core/parser/PDFParser.d.ts +2 -2
  97. package/ts3.4/es/api/PDFDocument.d.ts +14 -0
  98. package/ts3.4/es/api/PDFDocumentOptions.d.ts +1 -0
  99. package/ts3.4/es/api/snapshot/DefaultDocumentSnapshot.d.ts +4 -0
  100. package/ts3.4/es/api/snapshot/DocumentSnapshot.d.ts +4 -0
  101. package/ts3.4/es/api/snapshot/IncrementalDocumentSnapshot.d.ts +5 -0
  102. package/ts3.4/es/core/PDFContext.d.ts +10 -1
  103. package/ts3.4/es/core/document/PDFCrossRefSection.d.ts +6 -1
  104. package/ts3.4/es/core/parser/PDFParser.d.ts +2 -2
package/dist/pdf-lib.js CHANGED
@@ -9284,12 +9284,20 @@
9284
9284
 
9285
9285
  const byAscendingObjectNumber = ([a], [b]) => a.objectNumber - b.objectNumber;
9286
9286
  class PDFContext {
9287
- constructor() {
9287
+ get preserveObjectsVersions() {
9288
+ return this._preserveObjectsVersions;
9289
+ }
9290
+ constructor(preserveObjectsVersions) {
9288
9291
  this.isDecrypted = true;
9292
+ this.xrefs = [];
9293
+ this._preserveObjectsVersions = preserveObjectsVersions
9294
+ ? preserveObjectsVersions
9295
+ : false;
9289
9296
  this.largestObjectNumber = 0;
9290
9297
  this.header = PDFHeader.forVersion(1, 7);
9291
9298
  this.trailerInfo = {};
9292
9299
  this.indirectObjects = new Map();
9300
+ this.objectsPreviousVersions = new Map();
9293
9301
  this.rng = SimpleRNG.withSeed(1);
9294
9302
  this.pdfFileDetails = {
9295
9303
  pdfSize: 0,
@@ -9298,6 +9306,18 @@
9298
9306
  };
9299
9307
  }
9300
9308
  assign(ref, object) {
9309
+ if (this.preserveObjectsVersions) {
9310
+ const prevOV = this.indirectObjects.get(ref);
9311
+ if (prevOV) {
9312
+ const prevList = this.objectsPreviousVersions.get(ref);
9313
+ if (!prevList) {
9314
+ this.objectsPreviousVersions.set(ref, [prevOV]);
9315
+ }
9316
+ else {
9317
+ prevList.unshift(prevOV);
9318
+ }
9319
+ }
9320
+ }
9301
9321
  this.indirectObjects.set(ref, object);
9302
9322
  if (ref.objectNumber > this.largestObjectNumber) {
9303
9323
  this.largestObjectNumber = ref.objectNumber;
@@ -9313,6 +9333,21 @@
9313
9333
  return ref;
9314
9334
  }
9315
9335
  delete(ref) {
9336
+ if (this.snapshot)
9337
+ this.snapshot.markDeletedRef(ref);
9338
+ if (this.preserveObjectsVersions) {
9339
+ const object = this.indirectObjects.get(ref);
9340
+ if (object) {
9341
+ // check is not already deleted
9342
+ const verlist = this.objectsPreviousVersions.get(ref);
9343
+ if (verlist) {
9344
+ verlist.unshift(object);
9345
+ }
9346
+ else {
9347
+ this.objectsPreviousVersions.set(ref, [object]);
9348
+ }
9349
+ }
9350
+ }
9316
9351
  return this.indirectObjects.delete(ref);
9317
9352
  }
9318
9353
  lookupMaybe(ref, ...types) {
@@ -9498,8 +9533,23 @@
9498
9533
  if (this.snapshot)
9499
9534
  this.snapshot.markObjForSave(obj);
9500
9535
  }
9536
+ getObjectVersions(ref) {
9537
+ if (!this.preserveObjectsVersions)
9538
+ return [];
9539
+ const list = this.objectsPreviousVersions.get(ref);
9540
+ if (list)
9541
+ return list;
9542
+ return [];
9543
+ }
9544
+ listXrefEntries(xrefIndex = -1) {
9545
+ if (xrefIndex < 0)
9546
+ xrefIndex = this.xrefs.length - 1;
9547
+ if (xrefIndex < 0 || xrefIndex >= this.xrefs.length)
9548
+ return [];
9549
+ return this.xrefs[xrefIndex].listRefs();
9550
+ }
9501
9551
  }
9502
- PDFContext.create = () => new PDFContext();
9552
+ PDFContext.create = (withObjectVersions = false) => new PDFContext(withObjectVersions);
9503
9553
 
9504
9554
  class PDFPageLeaf extends PDFDict {
9505
9555
  constructor(map, context, autoNormalizeCTM = true) {
@@ -9846,6 +9896,7 @@
9846
9896
  constructor() {
9847
9897
  this.pdfSize = 0;
9848
9898
  this.prevStartXRef = 0;
9899
+ this.deletedCount = 0;
9849
9900
  }
9850
9901
  shouldSave(_objectNumber) {
9851
9902
  return true;
@@ -9862,11 +9913,22 @@
9862
9913
  markObjsForSave(_objs) {
9863
9914
  throw new Error('This method should not be called.');
9864
9915
  }
9916
+ markDeletedObj(_obj) {
9917
+ throw new Error('This method should not be called.');
9918
+ }
9919
+ markDeletedRef(_ref) {
9920
+ throw new Error('This method should not be called.');
9921
+ }
9922
+ deletedRef(_index) {
9923
+ throw new Error('This method should not be called.');
9924
+ }
9865
9925
  }
9866
9926
  const defaultDocumentSnapshot = new DefaultDocumentSnapshot();
9867
9927
 
9868
9928
  class IncrementalDocumentSnapshot {
9869
9929
  constructor(lastObjectNumber, indirectObjects, pdfSize, prevStartXRef, context) {
9930
+ this.deletedCount = 0;
9931
+ this.deleted = [];
9870
9932
  this.lastObjectNumber = lastObjectNumber;
9871
9933
  this.changedObjects = indirectObjects;
9872
9934
  this.pdfSize = pdfSize;
@@ -9899,11 +9961,26 @@
9899
9961
  .map((obj) => this.context.getRef(obj))
9900
9962
  .filter((ref) => ref !== undefined));
9901
9963
  }
9964
+ markDeletedRef(ref) {
9965
+ if (this.deleted.findIndex((dref) => dref.objectNumber === ref.objectNumber) <
9966
+ 0)
9967
+ this.deletedCount = this.deleted.push(ref);
9968
+ }
9969
+ markDeletedObj(obj) {
9970
+ const oref = this.context.getRef(obj);
9971
+ if (oref)
9972
+ this.markDeletedRef(oref);
9973
+ }
9974
+ deletedRef(index) {
9975
+ if (index < 0 || index >= this.deleted.length)
9976
+ return null;
9977
+ return this.deleted[index];
9978
+ }
9902
9979
  }
9903
9980
 
9904
9981
  /**
9905
9982
  * Entries should be added using the [[addEntry]] and [[addDeletedEntry]]
9906
- * methods **in order of ascending object number**.
9983
+ * methods.
9907
9984
  */
9908
9985
  class PDFCrossRefSection {
9909
9986
  constructor(firstEntry) {
@@ -9915,6 +9992,23 @@
9915
9992
  this.append({ ref, offset, deleted: false });
9916
9993
  }
9917
9994
  addDeletedEntry(ref, nextFreeObjectNumber) {
9995
+ // fix the first entry if required
9996
+ if (!this.subsections.length) {
9997
+ this.subsections = [
9998
+ [
9999
+ {
10000
+ ref: PDFRef.of(0, 65535),
10001
+ offset: ref.objectNumber,
10002
+ deleted: true,
10003
+ },
10004
+ ],
10005
+ ];
10006
+ this.chunkIdx = 0;
10007
+ this.chunkLength = 1;
10008
+ }
10009
+ else if (!this.subsections[0][0].offset) {
10010
+ this.subsections[0][0].offset = ref.objectNumber;
10011
+ }
9918
10012
  this.append({ ref, offset: nextFreeObjectNumber, deleted: true });
9919
10013
  }
9920
10014
  toString() {
@@ -9997,7 +10091,37 @@
9997
10091
  }
9998
10092
  const chunk = this.subsections[this.chunkIdx];
9999
10093
  const prevEntry = chunk[this.chunkLength - 1];
10000
- if (currEntry.ref.objectNumber - prevEntry.ref.objectNumber > 1) {
10094
+ if (currEntry.ref.objectNumber - prevEntry.ref.objectNumber !== 1) {
10095
+ // the current chunk is not the right chunk, find the right one, or create a new one
10096
+ for (let c = 0; c < this.subsections.length; c++) {
10097
+ const first = this.subsections[c][0];
10098
+ const last = this.subsections[c][this.subsections[c].length - 1];
10099
+ if (first.ref.objectNumber > currEntry.ref.objectNumber) {
10100
+ // goes before this subsection, or at the start of it
10101
+ if (first.ref.objectNumber - currEntry.ref.objectNumber === 1) {
10102
+ // first element of subsection
10103
+ this.subsections[c].unshift(currEntry);
10104
+ if (c === this.chunkIdx)
10105
+ this.chunkLength += 1;
10106
+ return;
10107
+ }
10108
+ else {
10109
+ // create subsection
10110
+ this.subsections.splice(c, 0, [currEntry]);
10111
+ this.chunkIdx++;
10112
+ return;
10113
+ }
10114
+ }
10115
+ else if (last.ref.objectNumber > currEntry.ref.objectNumber) {
10116
+ // goes in this subsection, find its place..
10117
+ const cep = this.subsections[c].findIndex((ee) => ee.ref.objectNumber > currEntry.ref.objectNumber);
10118
+ this.subsections[c].splice(cep, 0, currEntry);
10119
+ if (c === this.chunkIdx)
10120
+ this.chunkLength += 1;
10121
+ }
10122
+ // bigger, keep looking
10123
+ }
10124
+ // if got to here, then a new subsection is required
10001
10125
  this.subsections.push([currEntry]);
10002
10126
  this.chunkIdx += 1;
10003
10127
  this.chunkLength = 1;
@@ -10007,6 +10131,22 @@
10007
10131
  this.chunkLength += 1;
10008
10132
  }
10009
10133
  }
10134
+ /**
10135
+ * Returns all the entries in the XREF section, except the first one (object == 0)
10136
+ * @returns {Entry[]} All the entries in the XREF section
10137
+ */
10138
+ listRefs() {
10139
+ const refList = [];
10140
+ for (let rangeIdx = 0, rangeLen = this.subsections.length; rangeIdx < rangeLen; rangeIdx++) {
10141
+ const range = this.subsections[rangeIdx];
10142
+ for (let entryIdx = 0, entryLen = range.length; entryIdx < entryLen; entryIdx++) {
10143
+ const entry = range[entryIdx];
10144
+ if (entry.ref.objectNumber)
10145
+ refList.push(entry);
10146
+ }
10147
+ }
10148
+ return refList;
10149
+ }
10010
10150
  }
10011
10151
  PDFCrossRefSection.create = () => new PDFCrossRefSection({
10012
10152
  ref: PDFRef.of(0, 65535),
@@ -10238,6 +10378,15 @@
10238
10378
  if (this.shouldWaitForTick(1))
10239
10379
  yield waitForTick();
10240
10380
  }
10381
+ // deleted objects
10382
+ for (let idx = 0; idx < this.snapshot.deletedCount; idx++) {
10383
+ const dref = this.snapshot.deletedRef(idx);
10384
+ if (!dref)
10385
+ break;
10386
+ const nextdref = this.snapshot.deletedRef(idx + 1);
10387
+ // add 1 to generation number for deleted ref
10388
+ xref.addDeletedEntry(PDFRef.of(dref.objectNumber, dref.generationNumber + 1), nextdref ? nextdref.objectNumber : 0);
10389
+ }
10241
10390
  const xrefOffset = size;
10242
10391
  size += xref.sizeInBytes() + 1; // '\n'
10243
10392
  const trailerDict = PDFTrailerDict.of(this.createTrailerDict(this.snapshot.prevStartXRef));
@@ -15770,11 +15919,17 @@ end\
15770
15919
  }
15771
15920
  this.alreadyParsed = true;
15772
15921
  this.context.trailerInfo = {
15922
+ Size: this.dict.lookup(PDFName.of('Size'), PDFNumber),
15773
15923
  Root: this.dict.get(PDFName.of('Root')),
15774
15924
  Encrypt: this.dict.get(PDFName.of('Encrypt')),
15775
15925
  Info: this.dict.get(PDFName.of('Info')),
15776
15926
  ID: this.dict.get(PDFName.of('ID')),
15777
15927
  };
15928
+ // if open for incremental update, make sure next object number doesn't overlap a deleted one
15929
+ if (this.context.trailerInfo.Size &&
15930
+ this.context.pdfFileDetails.originalBytes)
15931
+ this.context.largestObjectNumber =
15932
+ this.context.trailerInfo.Size.asNumber() - 1;
15778
15933
  const entries = this.parseEntries();
15779
15934
  // for (let idx = 0, len = entries.length; idx < len; idx++) {
15780
15935
  // const entry = entries[idx];
@@ -15819,8 +15974,8 @@ end\
15819
15974
  PDFXRefStreamParser.forStream = (rawStream) => new PDFXRefStreamParser(rawStream);
15820
15975
 
15821
15976
  class PDFParser extends PDFObjectParser {
15822
- constructor(pdfBytes, objectsPerTick = Infinity, throwOnInvalidObject = false, warnOnInvalidObjects = false, capNumbers = false, cryptoFactory, forIncrementalUpdate = false) {
15823
- super(ByteStream.of(pdfBytes), PDFContext.create(), capNumbers, cryptoFactory);
15977
+ constructor(pdfBytes, objectsPerTick = Infinity, throwOnInvalidObject = false, warnOnInvalidObjects = false, capNumbers = false, cryptoFactory, forIncrementalUpdate = false, preserveObjectsVersions = false) {
15978
+ super(ByteStream.of(pdfBytes), PDFContext.create(preserveObjectsVersions), capNumbers, cryptoFactory);
15824
15979
  this.alreadyParsed = false;
15825
15980
  this.parsedObjects = 0;
15826
15981
  this.shouldWaitForTick = () => {
@@ -15927,7 +16082,17 @@ end\
15927
16082
  }
15928
16083
  else if (object instanceof PDFRawStream &&
15929
16084
  object.dict.lookup(PDFName.of('Type')) === PDFName.of('XRef')) {
15930
- PDFXRefStreamParser.forStream(object).parseIntoContext();
16085
+ const entries = PDFXRefStreamParser.forStream(object).parseIntoContext();
16086
+ if (entries.length) {
16087
+ const xref = PDFCrossRefSection.createEmpty();
16088
+ for (const entry of entries) {
16089
+ if (entry.deleted)
16090
+ xref.addDeletedEntry(entry.ref, entry.offset);
16091
+ else
16092
+ xref.addEntry(entry.ref, entry.offset);
16093
+ }
16094
+ this.context.xrefs.push(xref);
16095
+ }
15931
16096
  }
15932
16097
  // always register the object and the ref, to properly handle object numeration
15933
16098
  this.context.assign(ref, object);
@@ -16027,11 +16192,16 @@ end\
16027
16192
  const dict = this.parseDict();
16028
16193
  const { context } = this;
16029
16194
  context.trailerInfo = {
16195
+ Size: dict.lookupMaybe(PDFName.of('Size'), PDFNumber) ||
16196
+ context.trailerInfo.Size,
16030
16197
  Root: dict.get(PDFName.of('Root')) || context.trailerInfo.Root,
16031
16198
  Encrypt: dict.get(PDFName.of('Encrypt')) || context.trailerInfo.Encrypt,
16032
16199
  Info: dict.get(PDFName.of('Info')) || context.trailerInfo.Info,
16033
16200
  ID: dict.get(PDFName.of('ID')) || context.trailerInfo.ID,
16034
16201
  };
16202
+ // if open for incremental update, then deleted objects need to be preserved, and largestObjectNumber has to be Size-1
16203
+ if (context.trailerInfo.Size && context.pdfFileDetails.originalBytes)
16204
+ context.largestObjectNumber = context.trailerInfo.Size.asNumber() - 1;
16035
16205
  }
16036
16206
  maybeParseTrailer() {
16037
16207
  this.skipWhitespaceAndComments();
@@ -16050,7 +16220,9 @@ end\
16050
16220
  parseDocumentSection() {
16051
16221
  return __awaiter(this, void 0, void 0, function* () {
16052
16222
  yield this.parseIndirectObjects();
16053
- this.maybeParseCrossRefSection();
16223
+ const xref = this.maybeParseCrossRefSection();
16224
+ if (xref)
16225
+ this.context.xrefs.push(xref);
16054
16226
  this.maybeParseTrailerDict();
16055
16227
  this.maybeParseTrailer();
16056
16228
  // TODO: Can this be done only when needed, to avoid harming performance?
@@ -16107,7 +16279,7 @@ end\
16107
16279
  }
16108
16280
  }
16109
16281
  }
16110
- PDFParser.forBytesWithOptions = (pdfBytes, objectsPerTick, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, cryptoFactory, forIncrementalUpdate) => new PDFParser(pdfBytes, objectsPerTick, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, cryptoFactory, forIncrementalUpdate);
16282
+ PDFParser.forBytesWithOptions = (pdfBytes, objectsPerTick, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, cryptoFactory, forIncrementalUpdate, preserveObjectsVersions) => new PDFParser(pdfBytes, objectsPerTick, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, cryptoFactory, forIncrementalUpdate, preserveObjectsVersions);
16111
16283
 
16112
16284
  var cryptoJs = {exports: {}};
16113
16285
 
@@ -35636,7 +35808,7 @@ end\
35636
35808
  */
35637
35809
  static load(pdf, options = {}) {
35638
35810
  return __awaiter(this, void 0, void 0, function* () {
35639
- const { ignoreEncryption = false, parseSpeed = exports.ParseSpeeds.Slow, throwOnInvalidObject = false, warnOnInvalidObjects = false, updateMetadata = true, capNumbers = false, password, forIncrementalUpdate = false, } = options;
35811
+ const { ignoreEncryption = false, parseSpeed = exports.ParseSpeeds.Slow, throwOnInvalidObject = false, warnOnInvalidObjects = false, updateMetadata = true, capNumbers = false, password, forIncrementalUpdate = false, preserveObjectsVersions = false, } = options;
35640
35812
  assertIs(pdf, 'pdf', ['string', Uint8Array, ArrayBuffer]);
35641
35813
  assertIs(ignoreEncryption, 'ignoreEncryption', ['boolean']);
35642
35814
  assertIs(parseSpeed, 'parseSpeed', ['number']);
@@ -35644,14 +35816,15 @@ end\
35644
35816
  assertIs(warnOnInvalidObjects, 'warnOnInvalidObjects', ['boolean']);
35645
35817
  assertIs(password, 'password', ['string', 'undefined']);
35646
35818
  assertIs(forIncrementalUpdate, 'forIncrementalUpdate', ['boolean']);
35819
+ assertIs(preserveObjectsVersions, 'preserveObjectsVersions', ['boolean']);
35647
35820
  const bytes = toUint8Array(pdf);
35648
- const context = yield PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, undefined, capNumbers, undefined, forIncrementalUpdate).parseDocument();
35821
+ const context = yield PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, undefined, capNumbers, undefined, forIncrementalUpdate, preserveObjectsVersions).parseDocument();
35649
35822
  if (!!context.lookup(context.trailerInfo.Encrypt) &&
35650
35823
  password !== undefined) {
35651
35824
  // Decrypt
35652
35825
  const fileIds = context.lookup(context.trailerInfo.ID, PDFArray);
35653
35826
  const encryptDict = context.lookup(context.trailerInfo.Encrypt, PDFDict);
35654
- const decryptedContext = yield PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, new CipherTransformFactory(encryptDict, fileIds.get(0).asBytes(), password), forIncrementalUpdate).parseDocument();
35827
+ const decryptedContext = yield PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, new CipherTransformFactory(encryptDict, fileIds.get(0).asBytes(), password), forIncrementalUpdate, preserveObjectsVersions).parseDocument();
35655
35828
  const pdfDoc = new PDFDocument(decryptedContext, true, updateMetadata);
35656
35829
  if (forIncrementalUpdate)
35657
35830
  pdfDoc.takeSnapshot();
@@ -36114,8 +36287,10 @@ end\
36114
36287
  if (this.pageCount === 0)
36115
36288
  throw new RemovePageFromEmptyDocumentError();
36116
36289
  assertRange(index, 'index', 0, pageCount - 1);
36290
+ const page = this.getPage(index);
36117
36291
  this.catalog.removeLeafNode(index);
36118
36292
  this.pageCount = pageCount - 1;
36293
+ this.context.delete(page.ref);
36119
36294
  }
36120
36295
  /**
36121
36296
  * Add a page to the end of this document. This method accepts three
@@ -36943,6 +37118,51 @@ end\
36943
37118
  }
36944
37119
  return snapshot;
36945
37120
  }
37121
+ /**
37122
+ * Returns the update version of the object as 'actual', and all the previous versions, of the objects
37123
+ * that has changed in the indicated update (or the last one).
37124
+ * If document wasn't load to preserve objects versions, an empty array is returned.
37125
+ * @param {number} lastUpdateMinusX If not the last update, how many updates before the last.
37126
+ * @returns {PDFObjectVersions[]} Objects modified in the update, and previous versions
37127
+ */
37128
+ getChangedObjects(lastUpdateMinusX = 0) {
37129
+ if (!this.context.preserveObjectsVersions)
37130
+ return [];
37131
+ if (lastUpdateMinusX < 0)
37132
+ lastUpdateMinusX = 0;
37133
+ const upind = this.context.xrefs.length - lastUpdateMinusX - 1;
37134
+ const entries = this.context.listXrefEntries(upind);
37135
+ if (!entries.length)
37136
+ return [];
37137
+ const changed = new Map();
37138
+ for (const entry of entries) {
37139
+ const ref = entry.ref;
37140
+ changed.set(ref, {
37141
+ ref,
37142
+ actual: entry.deleted ? undefined : this.context.lookup(ref),
37143
+ previous: this.context.getObjectVersions(ref),
37144
+ });
37145
+ }
37146
+ // if not the las update, then check objects later modified and adjust PDFObjectVersions accordingly
37147
+ if (!lastUpdateMinusX)
37148
+ return Array.from(changed.entries()).map((value) => value[1]);
37149
+ while (lastUpdateMinusX) {
37150
+ lastUpdateMinusX -= 1;
37151
+ const upind = this.context.xrefs.length - lastUpdateMinusX - 1;
37152
+ const nentries = this.context.listXrefEntries(upind);
37153
+ for (const nentry of nentries) {
37154
+ const oce = changed.get(nentry.ref);
37155
+ if (oce && oce.actual) {
37156
+ oce.actual = oce.previous[0];
37157
+ oce.previous = oce.previous.slice(1);
37158
+ }
37159
+ }
37160
+ }
37161
+ // if PDF has errors, it may happen to end with objects that has no current, nor previous versions
37162
+ return Array.from(changed.entries())
37163
+ .map((value) => value[1])
37164
+ .filter((ov) => ov.actual || ov.previous.length);
37165
+ }
36946
37166
  prepareForSave(options) {
36947
37167
  return __awaiter(this, void 0, void 0, function* () {
36948
37168
  const { addDefaultPage = true, updateFieldAppearances = true } = options;