@adnsistemas/pdf-lib 2.7.2 → 2.8.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 (90) hide show
  1. package/README.md +5 -3
  2. package/cjs/api/PDFDocument.d.ts +16 -2
  3. package/cjs/api/PDFDocument.d.ts.map +1 -1
  4. package/cjs/api/PDFDocument.js +59 -5
  5. package/cjs/api/PDFDocument.js.map +1 -1
  6. package/cjs/api/PDFEmbeddedFile.d.ts +6 -0
  7. package/cjs/api/PDFEmbeddedFile.d.ts.map +1 -1
  8. package/cjs/api/PDFEmbeddedFile.js +10 -0
  9. package/cjs/api/PDFEmbeddedFile.js.map +1 -1
  10. package/cjs/api/PDFPage.js +1 -1
  11. package/cjs/api/operations.js +2 -2
  12. package/cjs/api/operations.js.map +1 -1
  13. package/cjs/api/snapshot/IncrementalDocumentSnapshot.d.ts +1 -1
  14. package/cjs/api/snapshot/IncrementalDocumentSnapshot.d.ts.map +1 -1
  15. package/cjs/api/snapshot/IncrementalDocumentSnapshot.js +3 -7
  16. package/cjs/api/snapshot/IncrementalDocumentSnapshot.js.map +1 -1
  17. package/cjs/core/embedders/JpegEmbedder.d.ts.map +1 -1
  18. package/cjs/core/embedders/JpegEmbedder.js +1 -1
  19. package/cjs/core/embedders/JpegEmbedder.js.map +1 -1
  20. package/cjs/core/objects/PDFString.js +1 -1
  21. package/cjs/core/parser/PDFObjectParser.d.ts.map +1 -1
  22. package/cjs/core/parser/PDFObjectParser.js +2 -1
  23. package/cjs/core/parser/PDFObjectParser.js.map +1 -1
  24. package/cjs/core/structures/PDFCatalog.d.ts +3 -0
  25. package/cjs/core/structures/PDFCatalog.d.ts.map +1 -1
  26. package/cjs/core/structures/PDFCatalog.js +7 -0
  27. package/cjs/core/structures/PDFCatalog.js.map +1 -1
  28. package/cjs/core/writers/PDFWriter.d.ts +8 -3
  29. package/cjs/core/writers/PDFWriter.d.ts.map +1 -1
  30. package/cjs/core/writers/PDFWriter.js +30 -7
  31. package/cjs/core/writers/PDFWriter.js.map +1 -1
  32. package/dist/pdf-lib.esm.js +115 -25
  33. package/dist/pdf-lib.esm.js.map +1 -1
  34. package/dist/pdf-lib.esm.min.js +3 -3
  35. package/dist/pdf-lib.esm.min.js.map +1 -1
  36. package/dist/pdf-lib.js +115 -25
  37. package/dist/pdf-lib.js.map +1 -1
  38. package/dist/pdf-lib.min.js +3 -3
  39. package/dist/pdf-lib.min.js.map +1 -1
  40. package/es/api/PDFDocument.d.ts +16 -2
  41. package/es/api/PDFDocument.d.ts.map +1 -1
  42. package/es/api/PDFDocument.js +59 -5
  43. package/es/api/PDFDocument.js.map +1 -1
  44. package/es/api/PDFEmbeddedFile.d.ts +6 -0
  45. package/es/api/PDFEmbeddedFile.d.ts.map +1 -1
  46. package/es/api/PDFEmbeddedFile.js +10 -0
  47. package/es/api/PDFEmbeddedFile.js.map +1 -1
  48. package/es/api/PDFPage.js +1 -1
  49. package/es/api/operations.js +2 -2
  50. package/es/api/operations.js.map +1 -1
  51. package/es/api/snapshot/IncrementalDocumentSnapshot.d.ts +1 -1
  52. package/es/api/snapshot/IncrementalDocumentSnapshot.d.ts.map +1 -1
  53. package/es/api/snapshot/IncrementalDocumentSnapshot.js +3 -7
  54. package/es/api/snapshot/IncrementalDocumentSnapshot.js.map +1 -1
  55. package/es/core/embedders/JpegEmbedder.d.ts.map +1 -1
  56. package/es/core/embedders/JpegEmbedder.js +1 -1
  57. package/es/core/embedders/JpegEmbedder.js.map +1 -1
  58. package/es/core/objects/PDFString.js +1 -1
  59. package/es/core/parser/PDFObjectParser.d.ts.map +1 -1
  60. package/es/core/parser/PDFObjectParser.js +3 -2
  61. package/es/core/parser/PDFObjectParser.js.map +1 -1
  62. package/es/core/structures/PDFCatalog.d.ts +3 -0
  63. package/es/core/structures/PDFCatalog.d.ts.map +1 -1
  64. package/es/core/structures/PDFCatalog.js +7 -0
  65. package/es/core/structures/PDFCatalog.js.map +1 -1
  66. package/es/core/writers/PDFWriter.d.ts +8 -3
  67. package/es/core/writers/PDFWriter.d.ts.map +1 -1
  68. package/es/core/writers/PDFWriter.js +30 -7
  69. package/es/core/writers/PDFWriter.js.map +1 -1
  70. package/package.json +4 -2
  71. package/src/api/PDFDocument.ts +75 -10
  72. package/src/api/PDFEmbeddedFile.ts +12 -0
  73. package/src/api/PDFPage.ts +1 -1
  74. package/src/api/operations.ts +2 -2
  75. package/src/api/snapshot/IncrementalDocumentSnapshot.ts +5 -11
  76. package/src/core/embedders/JpegEmbedder.ts +5 -1
  77. package/src/core/objects/PDFString.ts +1 -1
  78. package/src/core/parser/PDFObjectParser.ts +5 -2
  79. package/src/core/structures/PDFCatalog.ts +9 -0
  80. package/src/core/writers/PDFWriter.ts +32 -9
  81. package/ts3.4/cjs/api/PDFDocument.d.ts +16 -2
  82. package/ts3.4/cjs/api/PDFEmbeddedFile.d.ts +6 -0
  83. package/ts3.4/cjs/api/snapshot/IncrementalDocumentSnapshot.d.ts +1 -1
  84. package/ts3.4/cjs/core/structures/PDFCatalog.d.ts +3 -0
  85. package/ts3.4/cjs/core/writers/PDFWriter.d.ts +11 -3
  86. package/ts3.4/es/api/PDFDocument.d.ts +16 -2
  87. package/ts3.4/es/api/PDFEmbeddedFile.d.ts +6 -0
  88. package/ts3.4/es/api/snapshot/IncrementalDocumentSnapshot.d.ts +1 -1
  89. package/ts3.4/es/core/structures/PDFCatalog.d.ts +3 -0
  90. package/ts3.4/es/core/writers/PDFWriter.d.ts +11 -3
package/dist/pdf-lib.js CHANGED
@@ -9008,7 +9008,7 @@
9008
9008
  pushByte(CharCodes$1.LeftParen);
9009
9009
  else if (byte === CharCodes$1.RightParen)
9010
9010
  pushByte(CharCodes$1.RightParen);
9011
- else if (byte === CharCodes$1.Backspace)
9011
+ else if (byte === CharCodes$1.BackSlash)
9012
9012
  pushByte(CharCodes$1.BackSlash);
9013
9013
  else if (byte >= CharCodes$1.Zero && byte <= CharCodes$1.Seven) {
9014
9014
  octal += char;
@@ -9988,13 +9988,9 @@
9988
9988
  this.context = context;
9989
9989
  }
9990
9990
  shouldSave(objectNumber) {
9991
- if (objectNumber > this.lastObjectNumber) {
9991
+ if (objectNumber > this.lastObjectNumber)
9992
9992
  return true;
9993
- }
9994
- if (this.changedObjects.includes(objectNumber)) {
9995
- return true;
9996
- }
9997
- return false;
9993
+ return this.changedObjects.has(objectNumber);
9998
9994
  }
9999
9995
  markRefForSave(ref) {
10000
9996
  this.markRefsForSave([ref]);
@@ -10002,7 +9998,7 @@
10002
9998
  markRefsForSave(refs) {
10003
9999
  refs.forEach((ref) => {
10004
10000
  if (ref)
10005
- this.changedObjects.push(ref.objectNumber);
10001
+ this.changedObjects.add(ref.objectNumber);
10006
10002
  });
10007
10003
  }
10008
10004
  markObjForSave(obj) {
@@ -10337,6 +10333,11 @@
10337
10333
  * be corrected, to be accurate.
10338
10334
  */
10339
10335
  this._largestSkippedObjectNum = 0;
10336
+ /**
10337
+ * Used to check wheter an object should be saved or not, preserves the object number of the
10338
+ * last XRef Stream object, if there is one.
10339
+ */
10340
+ this._lastXRefObjectNumber = 0;
10340
10341
  this.shouldWaitForTick = (n) => {
10341
10342
  this.parsedObjects += n;
10342
10343
  return this.parsedObjects % this.objectsPerTick === 0;
@@ -10347,20 +10348,37 @@
10347
10348
  }
10348
10349
  /**
10349
10350
  * For incremental saves, defers the decision to the snapshot.
10350
- * For full saves, checks that the object is not an XRef stream object.
10351
+ * For full saves, checks that the object is not the last XRef stream object.
10351
10352
  * @param {boolean} incremental If making an incremental save, or a full save of the PDF
10352
10353
  * @param {number} objNum Object number
10353
- * @param {PDFObject} object PDFObject used to check if it is an XRef stream, when not 'incremental' saving
10354
+ * @param {[PDFRef, PDFObject][]} objects List of objects that form the PDF
10354
10355
  * @returns {boolean} whether the object should be saved or not
10355
10356
  */
10356
- shouldSave(incremental, objNum, object) {
10357
+ shouldSave(incremental, objNum, objects) {
10357
10358
  let should = true;
10358
10359
  if (incremental) {
10359
10360
  should = this.snapshot.shouldSave(objNum);
10360
10361
  }
10361
10362
  else {
10362
- should = !(object instanceof PDFRawStream &&
10363
- object.dict.lookup(PDFName.of('Type')) === PDFName.of('XRef'));
10363
+ // only the last XRef Stream will be regenerated on save
10364
+ if (!this._lastXRefObjectNumber) {
10365
+ // if no XRef Stream, then nothing should be skipped
10366
+ this._lastXRefObjectNumber = this.context.largestObjectNumber + 1;
10367
+ const checkWatermark = this._lastXRefObjectNumber - 10; // max number of objects in the final part of the PDF to check
10368
+ // search the last XRef Stream, if there is one, objects are expected to be in object number order
10369
+ for (let idx = objects.length - 1; idx > 0; idx--) {
10370
+ // if not in last 'rangeToCheck' objects, there is none that should be skipped, most probably a linearized PDF, or without XRef Streams
10371
+ if (objects[idx][0].objectNumber < checkWatermark)
10372
+ break;
10373
+ const object = objects[idx][1];
10374
+ if (object instanceof PDFRawStream &&
10375
+ object.dict.lookup(PDFName.of('Type')) === PDFName.of('XRef')) {
10376
+ this._lastXRefObjectNumber = objects[idx][0].objectNumber;
10377
+ break;
10378
+ }
10379
+ }
10380
+ }
10381
+ should = objNum !== this._lastXRefObjectNumber;
10364
10382
  }
10365
10383
  if (!should && this._largestSkippedObjectNum < objNum)
10366
10384
  this._largestSkippedObjectNum = objNum;
@@ -10379,7 +10397,7 @@
10379
10397
  buffer[offset++] = CharCodes$1.Newline;
10380
10398
  for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
10381
10399
  const [ref, object] = indirectObjects[idx];
10382
- if (!this.shouldSave(incremental, ref.objectNumber, object)) {
10400
+ if (!this.shouldSave(incremental, ref.objectNumber, indirectObjects)) {
10383
10401
  continue;
10384
10402
  }
10385
10403
  const objectNumber = String(ref.objectNumber);
@@ -10445,6 +10463,7 @@
10445
10463
  computeBufferSize(incremental) {
10446
10464
  return __awaiter(this, void 0, void 0, function* () {
10447
10465
  this._largestSkippedObjectNum = 0;
10466
+ this._lastXRefObjectNumber = 0;
10448
10467
  const header = PDFHeader.forVersion(1, 7);
10449
10468
  let size = this.snapshot.pdfSize;
10450
10469
  if (!incremental) {
@@ -10457,7 +10476,7 @@
10457
10476
  for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
10458
10477
  const indirectObject = indirectObjects[idx];
10459
10478
  const [ref, object] = indirectObject;
10460
- if (!this.shouldSave(incremental, ref.objectNumber, object))
10479
+ if (!this.shouldSave(incremental, ref.objectNumber, indirectObjects))
10461
10480
  continue;
10462
10481
  if (security)
10463
10482
  this.encrypt(ref, object, security);
@@ -12432,6 +12451,12 @@
12432
12451
  AcroForm() {
12433
12452
  return this.lookupMaybe(PDFName.of('AcroForm'), PDFDict);
12434
12453
  }
12454
+ Names() {
12455
+ return this.lookupMaybe(PDFName.of('Names'), PDFDict);
12456
+ }
12457
+ AttachedFiles() {
12458
+ return this.lookupMaybe(PDFName.of('AF'), PDFArray);
12459
+ }
12435
12460
  getAcroForm() {
12436
12461
  const dict = this.AcroForm();
12437
12462
  if (!dict)
@@ -13262,7 +13287,7 @@ end\
13262
13287
  class JpegEmbedder {
13263
13288
  static for(imageData) {
13264
13289
  return __awaiter(this, void 0, void 0, function* () {
13265
- const dataView = new DataView(imageData.buffer);
13290
+ const dataView = new DataView(imageData.buffer, imageData.byteOffset, imageData.byteLength);
13266
13291
  const soi = dataView.getUint16(0);
13267
13292
  if (soi !== 0xffd8)
13268
13293
  throw new Error('SOI not found in JPEG');
@@ -15919,7 +15944,8 @@ end\
15919
15944
  let actualValue = value.substring(1, value.length - 1);
15920
15945
  if (this.cryptoFactory && ref) {
15921
15946
  const transformer = this.cryptoFactory.createCipherTransform(ref.objectNumber, ref.generationNumber);
15922
- actualValue = transformer.decryptString(actualValue);
15947
+ const decrypted = transformer.decryptBytes(PDFString.of(actualValue).asBytes());
15948
+ actualValue = arrayAsString(decrypted);
15923
15949
  }
15924
15950
  // Remove the outer parens so they aren't part of the contents
15925
15951
  return PDFString.of(actualValue);
@@ -29503,13 +29529,13 @@ end\
29503
29529
  ];
29504
29530
  };
29505
29531
  const getDrawingOperator = ({ color, borderWidth, borderColor, fillRule, }) => {
29506
- if (color && borderColor && borderWidth) {
29532
+ if (color && borderColor && borderWidth !== 0) {
29507
29533
  return fillAndStroke;
29508
29534
  }
29509
29535
  else if (color) {
29510
29536
  return fillRule === exports.FillRule.EvenOdd ? fillEvenOdd : fill;
29511
29537
  }
29512
- else if (borderColor && borderWidth) {
29538
+ else if (borderColor && borderWidth !== 0) {
29513
29539
  return stroke;
29514
29540
  }
29515
29541
  return undefined;
@@ -34214,6 +34240,16 @@ end\
34214
34240
  getEmbedder() {
34215
34241
  return this.embedder;
34216
34242
  }
34243
+ /**
34244
+ * Returns whether or not this file has already been embedded.
34245
+ * @returns true if the file has already been embedded, false otherwise.
34246
+ */
34247
+ getAlreadyEmbedded() {
34248
+ return this.alreadyEmbedded;
34249
+ }
34250
+ getRef() {
34251
+ return this.ref;
34252
+ }
34217
34253
  }
34218
34254
  /**
34219
34255
  * > **NOTE:** You probably don't want to call this method directly. Instead,
@@ -36776,13 +36812,17 @@ end\
36776
36812
  for (let idx = 0, len = EFNames.size(); idx < len; idx += 2) {
36777
36813
  const fileName = EFNames.lookup(idx);
36778
36814
  const fileSpec = EFNames.lookup(idx + 1, PDFDict);
36779
- rawAttachments.push({ fileName, fileSpec });
36815
+ rawAttachments.push({
36816
+ fileName,
36817
+ fileSpec,
36818
+ specRef: EFNames.get(idx + 1),
36819
+ });
36780
36820
  }
36781
36821
  return rawAttachments;
36782
36822
  }
36783
36823
  getSavedAttachments() {
36784
36824
  const rawAttachments = this.getRawAttachments();
36785
- return rawAttachments.flatMap(({ fileName, fileSpec }) => {
36825
+ return rawAttachments.flatMap(({ fileName, fileSpec, specRef }) => {
36786
36826
  const efDict = fileSpec.lookup(PDFName.of('EF'));
36787
36827
  if (!(efDict instanceof PDFDict))
36788
36828
  return [];
@@ -36815,7 +36855,11 @@ end\
36815
36855
  modificationDate = modDateRaw.decodeDate();
36816
36856
  }
36817
36857
  }
36818
- const description = fileSpec.lookup(PDFName.of('Desc')).decodeText();
36858
+ const descRaw = fileSpec.lookup(PDFName.of('Desc'));
36859
+ let description;
36860
+ if (descRaw instanceof PDFHexString) {
36861
+ description = descRaw.decodeText();
36862
+ }
36819
36863
  return [
36820
36864
  {
36821
36865
  name: fileName.decodeText(),
@@ -36825,12 +36869,16 @@ end\
36825
36869
  description,
36826
36870
  creationDate,
36827
36871
  modificationDate,
36872
+ embeddedFileDict: efDict,
36873
+ specRef,
36828
36874
  },
36829
36875
  ];
36830
36876
  });
36831
36877
  }
36832
36878
  getUnsavedAttachments() {
36833
- const attachments = this.embeddedFiles.map((file) => {
36879
+ const attachments = this.embeddedFiles.flatMap((file) => {
36880
+ if (file.getAlreadyEmbedded())
36881
+ return [];
36834
36882
  const embedder = file.getEmbedder();
36835
36883
  return {
36836
36884
  name: embedder.fileName,
@@ -36840,6 +36888,7 @@ end\
36840
36888
  afRelationship: embedder.options.afRelationship,
36841
36889
  creationDate: embedder.options.creationDate,
36842
36890
  modificationDate: embedder.options.modificationDate,
36891
+ pdfEmbeddedFile: file,
36843
36892
  };
36844
36893
  });
36845
36894
  return attachments;
@@ -36854,6 +36903,47 @@ end\
36854
36903
  const unsavedAttachments = this.getUnsavedAttachments();
36855
36904
  return [...savedAttachments, ...unsavedAttachments];
36856
36905
  }
36906
+ /**
36907
+ * Removes an attachment from PDF, based on name.
36908
+ * @param {string} name Name of the attachmet to remove.
36909
+ */
36910
+ detach(name) {
36911
+ const attachedFiles = this.getAttachments();
36912
+ attachedFiles.forEach((file) => {
36913
+ var _a, _b, _c;
36914
+ if (file.name !== name)
36915
+ return;
36916
+ // the file wasn't embedded into context yet
36917
+ if ('pdfEmbeddedFile' in file) {
36918
+ const i = this.embeddedFiles.findIndex((f) => file.pdfEmbeddedFile === f);
36919
+ if (i !== undefined)
36920
+ this.embeddedFiles.splice(i, 1);
36921
+ }
36922
+ else {
36923
+ // remove references from catalog
36924
+ const namesArr = (_a = this.catalog
36925
+ .Names()) === null || _a === void 0 ? void 0 : _a.lookup(PDFName.of('EmbeddedFiles'), PDFDict).lookup(PDFName.of('Names'), PDFArray);
36926
+ const iNames = namesArr === null || namesArr === void 0 ? void 0 : namesArr.indexOf(file.specRef);
36927
+ if (iNames !== undefined && iNames > 0) {
36928
+ // attachment spec ref
36929
+ namesArr === null || namesArr === void 0 ? void 0 : namesArr.remove(iNames);
36930
+ // attachment name
36931
+ namesArr === null || namesArr === void 0 ? void 0 : namesArr.remove(iNames - 1);
36932
+ }
36933
+ // AF-Tag for PDF-A3 compliance
36934
+ const AF = this.catalog.AttachedFiles();
36935
+ const afIndex = AF === null || AF === void 0 ? void 0 : AF.indexOf(file.specRef);
36936
+ if (afIndex !== undefined)
36937
+ AF === null || AF === void 0 ? void 0 : AF.remove(afIndex);
36938
+ // remove references from context
36939
+ const streamRef = (_c = (_b = this.context
36940
+ .lookupMaybe(file.specRef, PDFDict)) === null || _b === void 0 ? void 0 : _b.lookupMaybe(PDFName.of('EF'), PDFDict)) === null || _c === void 0 ? void 0 : _c.get(PDFName.of('F'));
36941
+ if (streamRef)
36942
+ this.context.delete(streamRef);
36943
+ this.context.delete(file.specRef);
36944
+ }
36945
+ });
36946
+ }
36857
36947
  /**
36858
36948
  * Embed a font into this document. The input data can be provided in multiple
36859
36949
  * formats:
@@ -37311,7 +37401,7 @@ end\
37311
37401
  return undefined;
37312
37402
  }
37313
37403
  takeSnapshot() {
37314
- const indirectObjects = [];
37404
+ const indirectObjects = new Set();
37315
37405
  const snapshot = new IncrementalDocumentSnapshot(this.context.largestObjectNumber, indirectObjects, this.context.pdfFileDetails.pdfSize, this.context.pdfFileDetails.prevStartXRef, this.context);
37316
37406
  if (!this.context.snapshot && this.context.pdfFileDetails.originalBytes) {
37317
37407
  this.context.snapshot = snapshot;
@@ -38545,7 +38635,7 @@ end\
38545
38635
  rotate: (_c = options.rotate) !== null && _c !== void 0 ? _c : degrees(0),
38546
38636
  color: (_d = options.color) !== null && _d !== void 0 ? _d : undefined,
38547
38637
  borderColor: (_e = options.borderColor) !== null && _e !== void 0 ? _e : undefined,
38548
- borderWidth: (_f = options.borderWidth) !== null && _f !== void 0 ? _f : 0,
38638
+ borderWidth: (_f = options.borderWidth) !== null && _f !== void 0 ? _f : 1,
38549
38639
  borderDashArray: (_g = options.borderDashArray) !== null && _g !== void 0 ? _g : undefined,
38550
38640
  borderDashPhase: (_h = options.borderDashPhase) !== null && _h !== void 0 ? _h : undefined,
38551
38641
  borderLineCap: (_j = options.borderLineCap) !== null && _j !== void 0 ? _j : undefined,