@adnsistemas/pdf-lib 2.5.0 → 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 (61) 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 +49 -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/core/PDFContext.d.ts +9 -1
  9. package/cjs/core/PDFContext.d.ts.map +1 -1
  10. package/cjs/core/PDFContext.js +50 -2
  11. package/cjs/core/PDFContext.js.map +1 -1
  12. package/cjs/core/document/PDFCrossRefSection.d.ts +5 -0
  13. package/cjs/core/document/PDFCrossRefSection.d.ts.map +1 -1
  14. package/cjs/core/document/PDFCrossRefSection.js +16 -0
  15. package/cjs/core/document/PDFCrossRefSection.js.map +1 -1
  16. package/cjs/core/parser/PDFParser.d.ts +2 -2
  17. package/cjs/core/parser/PDFParser.d.ts.map +1 -1
  18. package/cjs/core/parser/PDFParser.js +17 -5
  19. package/cjs/core/parser/PDFParser.js.map +1 -1
  20. package/dist/pdf-lib.esm.js +132 -10
  21. package/dist/pdf-lib.esm.js.map +1 -1
  22. package/dist/pdf-lib.esm.min.js +3 -3
  23. package/dist/pdf-lib.esm.min.js.map +1 -1
  24. package/dist/pdf-lib.js +132 -10
  25. package/dist/pdf-lib.js.map +1 -1
  26. package/dist/pdf-lib.min.js +3 -3
  27. package/dist/pdf-lib.min.js.map +1 -1
  28. package/es/api/PDFDocument.d.ts +14 -0
  29. package/es/api/PDFDocument.d.ts.map +1 -1
  30. package/es/api/PDFDocument.js +49 -3
  31. package/es/api/PDFDocument.js.map +1 -1
  32. package/es/api/PDFDocumentOptions.d.ts +1 -0
  33. package/es/api/PDFDocumentOptions.d.ts.map +1 -1
  34. package/es/core/PDFContext.d.ts +9 -1
  35. package/es/core/PDFContext.d.ts.map +1 -1
  36. package/es/core/PDFContext.js +50 -2
  37. package/es/core/PDFContext.js.map +1 -1
  38. package/es/core/document/PDFCrossRefSection.d.ts +5 -0
  39. package/es/core/document/PDFCrossRefSection.d.ts.map +1 -1
  40. package/es/core/document/PDFCrossRefSection.js +16 -0
  41. package/es/core/document/PDFCrossRefSection.js.map +1 -1
  42. package/es/core/parser/PDFParser.d.ts +2 -2
  43. package/es/core/parser/PDFParser.d.ts.map +1 -1
  44. package/es/core/parser/PDFParser.js +17 -5
  45. package/es/core/parser/PDFParser.js.map +1 -1
  46. package/package.json +3 -3
  47. package/src/api/PDFDocument.ts +53 -0
  48. package/src/api/PDFDocumentOptions.ts +1 -0
  49. package/src/core/PDFContext.ts +51 -2
  50. package/src/core/document/PDFCrossRefSection.ts +24 -0
  51. package/src/core/parser/PDFParser.ts +15 -3
  52. package/ts3.4/cjs/api/PDFDocument.d.ts +14 -0
  53. package/ts3.4/cjs/api/PDFDocumentOptions.d.ts +1 -0
  54. package/ts3.4/cjs/core/PDFContext.d.ts +9 -1
  55. package/ts3.4/cjs/core/document/PDFCrossRefSection.d.ts +5 -0
  56. package/ts3.4/cjs/core/parser/PDFParser.d.ts +2 -2
  57. package/ts3.4/es/api/PDFDocument.d.ts +14 -0
  58. package/ts3.4/es/api/PDFDocumentOptions.d.ts +1 -0
  59. package/ts3.4/es/core/PDFContext.d.ts +9 -1
  60. package/ts3.4/es/core/document/PDFCrossRefSection.d.ts +5 -0
  61. 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;
@@ -9315,6 +9335,19 @@
9315
9335
  delete(ref) {
9316
9336
  if (this.snapshot)
9317
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
+ }
9318
9351
  return this.indirectObjects.delete(ref);
9319
9352
  }
9320
9353
  lookupMaybe(ref, ...types) {
@@ -9500,8 +9533,23 @@
9500
9533
  if (this.snapshot)
9501
9534
  this.snapshot.markObjForSave(obj);
9502
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
+ }
9503
9551
  }
9504
- PDFContext.create = () => new PDFContext();
9552
+ PDFContext.create = (withObjectVersions = false) => new PDFContext(withObjectVersions);
9505
9553
 
9506
9554
  class PDFPageLeaf extends PDFDict {
9507
9555
  constructor(map, context, autoNormalizeCTM = true) {
@@ -10083,6 +10131,22 @@
10083
10131
  this.chunkLength += 1;
10084
10132
  }
10085
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
+ }
10086
10150
  }
10087
10151
  PDFCrossRefSection.create = () => new PDFCrossRefSection({
10088
10152
  ref: PDFRef.of(0, 65535),
@@ -15910,8 +15974,8 @@ end\
15910
15974
  PDFXRefStreamParser.forStream = (rawStream) => new PDFXRefStreamParser(rawStream);
15911
15975
 
15912
15976
  class PDFParser extends PDFObjectParser {
15913
- constructor(pdfBytes, objectsPerTick = Infinity, throwOnInvalidObject = false, warnOnInvalidObjects = false, capNumbers = false, cryptoFactory, forIncrementalUpdate = false) {
15914
- 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);
15915
15979
  this.alreadyParsed = false;
15916
15980
  this.parsedObjects = 0;
15917
15981
  this.shouldWaitForTick = () => {
@@ -16018,7 +16082,17 @@ end\
16018
16082
  }
16019
16083
  else if (object instanceof PDFRawStream &&
16020
16084
  object.dict.lookup(PDFName.of('Type')) === PDFName.of('XRef')) {
16021
- 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
+ }
16022
16096
  }
16023
16097
  // always register the object and the ref, to properly handle object numeration
16024
16098
  this.context.assign(ref, object);
@@ -16146,7 +16220,9 @@ end\
16146
16220
  parseDocumentSection() {
16147
16221
  return __awaiter(this, void 0, void 0, function* () {
16148
16222
  yield this.parseIndirectObjects();
16149
- this.maybeParseCrossRefSection();
16223
+ const xref = this.maybeParseCrossRefSection();
16224
+ if (xref)
16225
+ this.context.xrefs.push(xref);
16150
16226
  this.maybeParseTrailerDict();
16151
16227
  this.maybeParseTrailer();
16152
16228
  // TODO: Can this be done only when needed, to avoid harming performance?
@@ -16203,7 +16279,7 @@ end\
16203
16279
  }
16204
16280
  }
16205
16281
  }
16206
- 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);
16207
16283
 
16208
16284
  var cryptoJs = {exports: {}};
16209
16285
 
@@ -35732,7 +35808,7 @@ end\
35732
35808
  */
35733
35809
  static load(pdf, options = {}) {
35734
35810
  return __awaiter(this, void 0, void 0, function* () {
35735
- 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;
35736
35812
  assertIs(pdf, 'pdf', ['string', Uint8Array, ArrayBuffer]);
35737
35813
  assertIs(ignoreEncryption, 'ignoreEncryption', ['boolean']);
35738
35814
  assertIs(parseSpeed, 'parseSpeed', ['number']);
@@ -35740,14 +35816,15 @@ end\
35740
35816
  assertIs(warnOnInvalidObjects, 'warnOnInvalidObjects', ['boolean']);
35741
35817
  assertIs(password, 'password', ['string', 'undefined']);
35742
35818
  assertIs(forIncrementalUpdate, 'forIncrementalUpdate', ['boolean']);
35819
+ assertIs(preserveObjectsVersions, 'preserveObjectsVersions', ['boolean']);
35743
35820
  const bytes = toUint8Array(pdf);
35744
- 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();
35745
35822
  if (!!context.lookup(context.trailerInfo.Encrypt) &&
35746
35823
  password !== undefined) {
35747
35824
  // Decrypt
35748
35825
  const fileIds = context.lookup(context.trailerInfo.ID, PDFArray);
35749
35826
  const encryptDict = context.lookup(context.trailerInfo.Encrypt, PDFDict);
35750
- 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();
35751
35828
  const pdfDoc = new PDFDocument(decryptedContext, true, updateMetadata);
35752
35829
  if (forIncrementalUpdate)
35753
35830
  pdfDoc.takeSnapshot();
@@ -37041,6 +37118,51 @@ end\
37041
37118
  }
37042
37119
  return snapshot;
37043
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
+ }
37044
37166
  prepareForSave(options) {
37045
37167
  return __awaiter(this, void 0, void 0, function* () {
37046
37168
  const { addDefaultPage = true, updateFieldAppearances = true } = options;