@adnsistemas/pdf-lib 2.5.0 → 2.6.1

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 +54 -3
  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 +136 -11
  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 +136 -11
  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 +54 -3
  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 +54 -3
  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;
@@ -9305,7 +9325,10 @@
9305
9325
  }
9306
9326
  nextRef() {
9307
9327
  this.largestObjectNumber += 1;
9308
- return PDFRef.of(this.largestObjectNumber);
9328
+ const ref = PDFRef.of(this.largestObjectNumber);
9329
+ if (this.snapshot)
9330
+ this.snapshot.markRefForSave(ref);
9331
+ return ref;
9309
9332
  }
9310
9333
  register(object) {
9311
9334
  const ref = this.nextRef();
@@ -9315,6 +9338,19 @@
9315
9338
  delete(ref) {
9316
9339
  if (this.snapshot)
9317
9340
  this.snapshot.markDeletedRef(ref);
9341
+ if (this.preserveObjectsVersions) {
9342
+ const object = this.indirectObjects.get(ref);
9343
+ if (object) {
9344
+ // check is not already deleted
9345
+ const verlist = this.objectsPreviousVersions.get(ref);
9346
+ if (verlist) {
9347
+ verlist.unshift(object);
9348
+ }
9349
+ else {
9350
+ this.objectsPreviousVersions.set(ref, [object]);
9351
+ }
9352
+ }
9353
+ }
9318
9354
  return this.indirectObjects.delete(ref);
9319
9355
  }
9320
9356
  lookupMaybe(ref, ...types) {
@@ -9500,8 +9536,23 @@
9500
9536
  if (this.snapshot)
9501
9537
  this.snapshot.markObjForSave(obj);
9502
9538
  }
9539
+ getObjectVersions(ref) {
9540
+ if (!this.preserveObjectsVersions)
9541
+ return [];
9542
+ const list = this.objectsPreviousVersions.get(ref);
9543
+ if (list)
9544
+ return list;
9545
+ return [];
9546
+ }
9547
+ listXrefEntries(xrefIndex = -1) {
9548
+ if (xrefIndex < 0)
9549
+ xrefIndex = this.xrefs.length - 1;
9550
+ if (xrefIndex < 0 || xrefIndex >= this.xrefs.length)
9551
+ return [];
9552
+ return this.xrefs[xrefIndex].listRefs();
9553
+ }
9503
9554
  }
9504
- PDFContext.create = () => new PDFContext();
9555
+ PDFContext.create = (withObjectVersions = false) => new PDFContext(withObjectVersions);
9505
9556
 
9506
9557
  class PDFPageLeaf extends PDFDict {
9507
9558
  constructor(map, context, autoNormalizeCTM = true) {
@@ -10083,6 +10134,22 @@
10083
10134
  this.chunkLength += 1;
10084
10135
  }
10085
10136
  }
10137
+ /**
10138
+ * Returns all the entries in the XREF section, except the first one (object == 0)
10139
+ * @returns {Entry[]} All the entries in the XREF section
10140
+ */
10141
+ listRefs() {
10142
+ const refList = [];
10143
+ for (let rangeIdx = 0, rangeLen = this.subsections.length; rangeIdx < rangeLen; rangeIdx++) {
10144
+ const range = this.subsections[rangeIdx];
10145
+ for (let entryIdx = 0, entryLen = range.length; entryIdx < entryLen; entryIdx++) {
10146
+ const entry = range[entryIdx];
10147
+ if (entry.ref.objectNumber)
10148
+ refList.push(entry);
10149
+ }
10150
+ }
10151
+ return refList;
10152
+ }
10086
10153
  }
10087
10154
  PDFCrossRefSection.create = () => new PDFCrossRefSection({
10088
10155
  ref: PDFRef.of(0, 65535),
@@ -15910,8 +15977,8 @@ end\
15910
15977
  PDFXRefStreamParser.forStream = (rawStream) => new PDFXRefStreamParser(rawStream);
15911
15978
 
15912
15979
  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);
15980
+ constructor(pdfBytes, objectsPerTick = Infinity, throwOnInvalidObject = false, warnOnInvalidObjects = false, capNumbers = false, cryptoFactory, forIncrementalUpdate = false, preserveObjectsVersions = false) {
15981
+ super(ByteStream.of(pdfBytes), PDFContext.create(preserveObjectsVersions), capNumbers, cryptoFactory);
15915
15982
  this.alreadyParsed = false;
15916
15983
  this.parsedObjects = 0;
15917
15984
  this.shouldWaitForTick = () => {
@@ -16018,7 +16085,17 @@ end\
16018
16085
  }
16019
16086
  else if (object instanceof PDFRawStream &&
16020
16087
  object.dict.lookup(PDFName.of('Type')) === PDFName.of('XRef')) {
16021
- PDFXRefStreamParser.forStream(object).parseIntoContext();
16088
+ const entries = PDFXRefStreamParser.forStream(object).parseIntoContext();
16089
+ if (entries.length) {
16090
+ const xref = PDFCrossRefSection.createEmpty();
16091
+ for (const entry of entries) {
16092
+ if (entry.deleted)
16093
+ xref.addDeletedEntry(entry.ref, entry.offset);
16094
+ else
16095
+ xref.addEntry(entry.ref, entry.offset);
16096
+ }
16097
+ this.context.xrefs.push(xref);
16098
+ }
16022
16099
  }
16023
16100
  // always register the object and the ref, to properly handle object numeration
16024
16101
  this.context.assign(ref, object);
@@ -16146,7 +16223,9 @@ end\
16146
16223
  parseDocumentSection() {
16147
16224
  return __awaiter(this, void 0, void 0, function* () {
16148
16225
  yield this.parseIndirectObjects();
16149
- this.maybeParseCrossRefSection();
16226
+ const xref = this.maybeParseCrossRefSection();
16227
+ if (xref)
16228
+ this.context.xrefs.push(xref);
16150
16229
  this.maybeParseTrailerDict();
16151
16230
  this.maybeParseTrailer();
16152
16231
  // TODO: Can this be done only when needed, to avoid harming performance?
@@ -16203,7 +16282,7 @@ end\
16203
16282
  }
16204
16283
  }
16205
16284
  }
16206
- PDFParser.forBytesWithOptions = (pdfBytes, objectsPerTick, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, cryptoFactory, forIncrementalUpdate) => new PDFParser(pdfBytes, objectsPerTick, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, cryptoFactory, forIncrementalUpdate);
16285
+ PDFParser.forBytesWithOptions = (pdfBytes, objectsPerTick, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, cryptoFactory, forIncrementalUpdate, preserveObjectsVersions) => new PDFParser(pdfBytes, objectsPerTick, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, cryptoFactory, forIncrementalUpdate, preserveObjectsVersions);
16207
16286
 
16208
16287
  var cryptoJs = {exports: {}};
16209
16288
 
@@ -35732,7 +35811,7 @@ end\
35732
35811
  */
35733
35812
  static load(pdf, options = {}) {
35734
35813
  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;
35814
+ const { ignoreEncryption = false, parseSpeed = exports.ParseSpeeds.Slow, throwOnInvalidObject = false, warnOnInvalidObjects = false, updateMetadata = true, capNumbers = false, password, forIncrementalUpdate = false, preserveObjectsVersions = false, } = options;
35736
35815
  assertIs(pdf, 'pdf', ['string', Uint8Array, ArrayBuffer]);
35737
35816
  assertIs(ignoreEncryption, 'ignoreEncryption', ['boolean']);
35738
35817
  assertIs(parseSpeed, 'parseSpeed', ['number']);
@@ -35740,14 +35819,15 @@ end\
35740
35819
  assertIs(warnOnInvalidObjects, 'warnOnInvalidObjects', ['boolean']);
35741
35820
  assertIs(password, 'password', ['string', 'undefined']);
35742
35821
  assertIs(forIncrementalUpdate, 'forIncrementalUpdate', ['boolean']);
35822
+ assertIs(preserveObjectsVersions, 'preserveObjectsVersions', ['boolean']);
35743
35823
  const bytes = toUint8Array(pdf);
35744
- const context = yield PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, undefined, capNumbers, undefined, forIncrementalUpdate).parseDocument();
35824
+ const context = yield PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, undefined, capNumbers, undefined, forIncrementalUpdate, preserveObjectsVersions).parseDocument();
35745
35825
  if (!!context.lookup(context.trailerInfo.Encrypt) &&
35746
35826
  password !== undefined) {
35747
35827
  // Decrypt
35748
35828
  const fileIds = context.lookup(context.trailerInfo.ID, PDFArray);
35749
35829
  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();
35830
+ const decryptedContext = yield PDFParser.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, warnOnInvalidObjects, capNumbers, new CipherTransformFactory(encryptDict, fileIds.get(0).asBytes(), password), forIncrementalUpdate, preserveObjectsVersions).parseDocument();
35751
35831
  const pdfDoc = new PDFDocument(decryptedContext, true, updateMetadata);
35752
35832
  if (forIncrementalUpdate)
35753
35833
  pdfDoc.takeSnapshot();
@@ -37041,6 +37121,51 @@ end\
37041
37121
  }
37042
37122
  return snapshot;
37043
37123
  }
37124
+ /**
37125
+ * Returns the update version of the object as 'actual', and all the previous versions, of the objects
37126
+ * that has changed in the indicated update (or the last one).
37127
+ * If document wasn't load to preserve objects versions, an empty array is returned.
37128
+ * @param {number} lastUpdateMinusX If not the last update, how many updates before the last.
37129
+ * @returns {PDFObjectVersions[]} Objects modified in the update, and previous versions
37130
+ */
37131
+ getChangedObjects(lastUpdateMinusX = 0) {
37132
+ if (!this.context.preserveObjectsVersions)
37133
+ return [];
37134
+ if (lastUpdateMinusX < 0)
37135
+ lastUpdateMinusX = 0;
37136
+ const upind = this.context.xrefs.length - lastUpdateMinusX - 1;
37137
+ const entries = this.context.listXrefEntries(upind);
37138
+ if (!entries.length)
37139
+ return [];
37140
+ const changed = new Map();
37141
+ for (const entry of entries) {
37142
+ const ref = entry.ref;
37143
+ changed.set(ref, {
37144
+ ref,
37145
+ actual: entry.deleted ? undefined : this.context.lookup(ref),
37146
+ previous: this.context.getObjectVersions(ref),
37147
+ });
37148
+ }
37149
+ // if not the las update, then check objects later modified and adjust PDFObjectVersions accordingly
37150
+ if (!lastUpdateMinusX)
37151
+ return Array.from(changed.entries()).map((value) => value[1]);
37152
+ while (lastUpdateMinusX) {
37153
+ lastUpdateMinusX -= 1;
37154
+ const upind = this.context.xrefs.length - lastUpdateMinusX - 1;
37155
+ const nentries = this.context.listXrefEntries(upind);
37156
+ for (const nentry of nentries) {
37157
+ const oce = changed.get(nentry.ref);
37158
+ if (oce && oce.actual) {
37159
+ oce.actual = oce.previous[0];
37160
+ oce.previous = oce.previous.slice(1);
37161
+ }
37162
+ }
37163
+ }
37164
+ // if PDF has errors, it may happen to end with objects that has no current, nor previous versions
37165
+ return Array.from(changed.entries())
37166
+ .map((value) => value[1])
37167
+ .filter((ov) => ov.actual || ov.previous.length);
37168
+ }
37044
37169
  prepareForSave(options) {
37045
37170
  return __awaiter(this, void 0, void 0, function* () {
37046
37171
  const { addDefaultPage = true, updateFieldAppearances = true } = options;