@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
@@ -5,6 +5,7 @@ import PDFContext from '../PDFContext';
5
5
  import PDFPageTree from './PDFPageTree';
6
6
  import { PDFAcroForm } from '../acroform';
7
7
  import ViewerPreferences from '../interactive/ViewerPreferences';
8
+ import PDFArray from '../objects/PDFArray';
8
9
 
9
10
  class PDFCatalog extends PDFDict {
10
11
  static withContextAndPages = (
@@ -28,6 +29,14 @@ class PDFCatalog extends PDFDict {
28
29
  return this.lookupMaybe(PDFName.of('AcroForm'), PDFDict);
29
30
  }
30
31
 
32
+ Names(): PDFDict | undefined {
33
+ return this.lookupMaybe(PDFName.of('Names'), PDFDict);
34
+ }
35
+
36
+ AttachedFiles(): PDFArray | undefined {
37
+ return this.lookupMaybe(PDFName.of('AF'), PDFArray);
38
+ }
39
+
31
40
  getAcroForm(): PDFAcroForm | undefined {
32
41
  const dict = this.AcroForm();
33
42
  if (!dict) return undefined;
@@ -62,27 +62,48 @@ class PDFWriter {
62
62
  */
63
63
  protected _largestSkippedObjectNum: number = 0;
64
64
 
65
+ /**
66
+ * Used to check wheter an object should be saved or not, preserves the object number of the
67
+ * last XRef Stream object, if there is one.
68
+ */
69
+ protected _lastXRefObjectNumber: number = 0;
65
70
  /**
66
71
  * For incremental saves, defers the decision to the snapshot.
67
- * For full saves, checks that the object is not an XRef stream object.
72
+ * For full saves, checks that the object is not the last XRef stream object.
68
73
  * @param {boolean} incremental If making an incremental save, or a full save of the PDF
69
74
  * @param {number} objNum Object number
70
- * @param {PDFObject} object PDFObject used to check if it is an XRef stream, when not 'incremental' saving
75
+ * @param {[PDFRef, PDFObject][]} objects List of objects that form the PDF
71
76
  * @returns {boolean} whether the object should be saved or not
72
77
  */
73
78
  protected shouldSave(
74
79
  incremental: boolean,
75
80
  objNum: number,
76
- object: PDFObject,
81
+ objects: [PDFRef, PDFObject][],
77
82
  ): boolean {
78
83
  let should = true;
79
84
  if (incremental) {
80
85
  should = this.snapshot.shouldSave(objNum);
81
86
  } else {
82
- should = !(
83
- object instanceof PDFRawStream &&
84
- object.dict.lookup(PDFName.of('Type')) === PDFName.of('XRef')
85
- );
87
+ // only the last XRef Stream will be regenerated on save
88
+ if (!this._lastXRefObjectNumber) {
89
+ // if no XRef Stream, then nothing should be skipped
90
+ this._lastXRefObjectNumber = this.context.largestObjectNumber + 1;
91
+ const checkWatermark = this._lastXRefObjectNumber - 10; // max number of objects in the final part of the PDF to check
92
+ // search the last XRef Stream, if there is one, objects are expected to be in object number order
93
+ for (let idx = objects.length - 1; idx > 0; idx--) {
94
+ // if not in last 'rangeToCheck' objects, there is none that should be skipped, most probably a linearized PDF, or without XRef Streams
95
+ if (objects[idx][0].objectNumber < checkWatermark) break;
96
+ const object = objects[idx][1];
97
+ if (
98
+ object instanceof PDFRawStream &&
99
+ object.dict.lookup(PDFName.of('Type')) === PDFName.of('XRef')
100
+ ) {
101
+ this._lastXRefObjectNumber = objects[idx][0].objectNumber;
102
+ break;
103
+ }
104
+ }
105
+ }
106
+ should = objNum !== this._lastXRefObjectNumber;
86
107
  }
87
108
  if (!should && this._largestSkippedObjectNum < objNum)
88
109
  this._largestSkippedObjectNum = objNum;
@@ -106,7 +127,7 @@ class PDFWriter {
106
127
  for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
107
128
  const [ref, object] = indirectObjects[idx];
108
129
 
109
- if (!this.shouldSave(incremental, ref.objectNumber, object)) {
130
+ if (!this.shouldSave(incremental, ref.objectNumber, indirectObjects)) {
110
131
  continue;
111
132
  }
112
133
 
@@ -189,6 +210,7 @@ class PDFWriter {
189
210
  incremental: boolean,
190
211
  ): Promise<SerializationInfo> {
191
212
  this._largestSkippedObjectNum = 0;
213
+ this._lastXRefObjectNumber = 0;
192
214
  const header = PDFHeader.forVersion(1, 7);
193
215
 
194
216
  let size = this.snapshot.pdfSize;
@@ -206,7 +228,8 @@ class PDFWriter {
206
228
  for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
207
229
  const indirectObject = indirectObjects[idx];
208
230
  const [ref, object] = indirectObject;
209
- if (!this.shouldSave(incremental, ref.objectNumber, object)) continue;
231
+ if (!this.shouldSave(incremental, ref.objectNumber, indirectObjects))
232
+ continue;
210
233
  if (security) this.encrypt(ref, object, security);
211
234
  xref.addEntry(ref, size);
212
235
  size += this.computeIndirectObjectSize(indirectObject);
@@ -4,17 +4,18 @@ import PDFImage from './PDFImage';
4
4
  import PDFPage from './PDFPage';
5
5
  import PDFForm from './form/PDFForm';
6
6
  import { StandardFonts } from './StandardFonts';
7
- import { PageBoundingBox, PDFCatalog, PDFContext } from '../core';
7
+ import { PageBoundingBox, PDFCatalog, PDFContext, PDFDict } from '../core';
8
8
  import { AttachmentOptions, SaveOptions, Base64SaveOptions, LoadOptions, CreateOptions, EmbedFontOptions, SetTitleOptions, IncrementalSaveOptions } from './PDFDocumentOptions';
9
9
  import PDFObject from '../core/objects/PDFObject';
10
10
  import PDFRef from '../core/objects/PDFRef';
11
11
  import { Fontkit } from '../types/fontkit';
12
12
  import { TransformationMatrix } from '../types/matrix';
13
13
  import { AFRelationship } from '../core/embedders/FileEmbedder';
14
+ import PDFEmbeddedFile from './PDFEmbeddedFile';
14
15
  import PDFSvg from './PDFSvg';
15
16
  import { SecurityOptions } from '../core/security/PDFSecurity';
16
17
  import { DocumentSnapshot } from './snapshot';
17
- export type PDFAttachment = {
18
+ export type BasePDFAttachment = {
18
19
  name: string;
19
20
  data: Uint8Array;
20
21
  mimeType: string | undefined;
@@ -23,6 +24,14 @@ export type PDFAttachment = {
23
24
  creationDate: Date | undefined;
24
25
  modificationDate: Date | undefined;
25
26
  };
27
+ export type SavedPDFAttachment = BasePDFAttachment & {
28
+ embeddedFileDict: PDFDict;
29
+ specRef: PDFRef;
30
+ };
31
+ export type UnsavedPDFAttachment = BasePDFAttachment & {
32
+ pdfEmbeddedFile: PDFEmbeddedFile;
33
+ };
34
+ export type PDFAttachment = UnsavedPDFAttachment | SavedPDFAttachment;
26
35
  export type PDFObjectVersions = {
27
36
  ref: PDFRef;
28
37
  actual: PDFObject | undefined;
@@ -575,6 +584,11 @@ export default class PDFDocument {
575
584
  * @returns Array of attachments with name and data
576
585
  */
577
586
  getAttachments(): PDFAttachment[];
587
+ /**
588
+ * Removes an attachment from PDF, based on name.
589
+ * @param {string} name Name of the attachmet to remove.
590
+ */
591
+ detach(name: string): void;
578
592
  /**
579
593
  * Embed a font into this document. The input data can be provided in multiple
580
594
  * formats:
@@ -40,5 +40,11 @@ export default class PDFEmbeddedFile implements Embeddable {
40
40
  * @returns the embedder.
41
41
  */
42
42
  getEmbedder(): FileEmbedder;
43
+ /**
44
+ * Returns whether or not this file has already been embedded.
45
+ * @returns true if the file has already been embedded, false otherwise.
46
+ */
47
+ getAlreadyEmbedded(): boolean;
48
+ getRef(): PDFRef;
43
49
  }
44
50
  //# sourceMappingURL=PDFEmbeddedFile.d.ts.map
@@ -8,7 +8,7 @@ export declare class IncrementalDocumentSnapshot implements DocumentSnapshot {
8
8
  private lastObjectNumber;
9
9
  private changedObjects;
10
10
  context: PDFContext;
11
- constructor(lastObjectNumber: number, indirectObjects: number[], pdfSize: number, prevStartXRef: number, context: PDFContext);
11
+ constructor(lastObjectNumber: number, indirectObjects: Set<number>, pdfSize: number, prevStartXRef: number, context: PDFContext);
12
12
  shouldSave(objectNumber: number): boolean;
13
13
  markRefForSave(ref: PDFRef): void;
14
14
  markRefsForSave(refs: PDFRef[]): void;
@@ -4,11 +4,14 @@ import PDFContext from '../PDFContext';
4
4
  import PDFPageTree from './PDFPageTree';
5
5
  import { PDFAcroForm } from '../acroform';
6
6
  import ViewerPreferences from '../interactive/ViewerPreferences';
7
+ import PDFArray from '../objects/PDFArray';
7
8
  declare class PDFCatalog extends PDFDict {
8
9
  static withContextAndPages: (context: PDFContext, pages: PDFPageTree | PDFRef) => PDFCatalog;
9
10
  static fromMapWithContext: (map: DictMap, context: PDFContext) => PDFCatalog;
10
11
  Pages(): PDFPageTree;
11
12
  AcroForm(): PDFDict | undefined;
13
+ Names(): PDFDict | undefined;
14
+ AttachedFiles(): PDFArray | undefined;
12
15
  getAcroForm(): PDFAcroForm | undefined;
13
16
  getOrCreateAcroForm(): PDFAcroForm;
14
17
  ViewerPreferences(): PDFDict | undefined;
@@ -33,15 +33,23 @@ declare class PDFWriter {
33
33
  * be corrected, to be accurate.
34
34
  */
35
35
  protected _largestSkippedObjectNum: number;
36
+ /**
37
+ * Used to check wheter an object should be saved or not, preserves the object number of the
38
+ * last XRef Stream object, if there is one.
39
+ */
40
+ protected _lastXRefObjectNumber: number;
36
41
  /**
37
42
  * For incremental saves, defers the decision to the snapshot.
38
- * For full saves, checks that the object is not an XRef stream object.
43
+ * For full saves, checks that the object is not the last XRef stream object.
39
44
  * @param {boolean} incremental If making an incremental save, or a full save of the PDF
40
45
  * @param {number} objNum Object number
41
- * @param {PDFObject} object PDFObject used to check if it is an XRef stream, when not 'incremental' saving
46
+ * @param {[PDFRef, PDFObject][]} objects List of objects that form the PDF
42
47
  * @returns {boolean} whether the object should be saved or not
43
48
  */
44
- protected shouldSave(incremental: boolean, objNum: number, object: PDFObject): boolean;
49
+ protected shouldSave(incremental: boolean, objNum: number, objects: [
50
+ PDFRef,
51
+ PDFObject
52
+ ][]): boolean;
45
53
  serializeToBuffer(): Promise<Uint8Array>;
46
54
  protected computeIndirectObjectSize([ref, object]: [
47
55
  PDFRef,
@@ -4,17 +4,18 @@ import PDFImage from './PDFImage';
4
4
  import PDFPage from './PDFPage';
5
5
  import PDFForm from './form/PDFForm';
6
6
  import { StandardFonts } from './StandardFonts';
7
- import { PageBoundingBox, PDFCatalog, PDFContext } from '../core';
7
+ import { PageBoundingBox, PDFCatalog, PDFContext, PDFDict } from '../core';
8
8
  import { AttachmentOptions, SaveOptions, Base64SaveOptions, LoadOptions, CreateOptions, EmbedFontOptions, SetTitleOptions, IncrementalSaveOptions } from './PDFDocumentOptions';
9
9
  import PDFObject from '../core/objects/PDFObject';
10
10
  import PDFRef from '../core/objects/PDFRef';
11
11
  import { Fontkit } from '../types/fontkit';
12
12
  import { TransformationMatrix } from '../types/matrix';
13
13
  import { AFRelationship } from '../core/embedders/FileEmbedder';
14
+ import PDFEmbeddedFile from './PDFEmbeddedFile';
14
15
  import PDFSvg from './PDFSvg';
15
16
  import { SecurityOptions } from '../core/security/PDFSecurity';
16
17
  import { DocumentSnapshot } from './snapshot';
17
- export type PDFAttachment = {
18
+ export type BasePDFAttachment = {
18
19
  name: string;
19
20
  data: Uint8Array;
20
21
  mimeType: string | undefined;
@@ -23,6 +24,14 @@ export type PDFAttachment = {
23
24
  creationDate: Date | undefined;
24
25
  modificationDate: Date | undefined;
25
26
  };
27
+ export type SavedPDFAttachment = BasePDFAttachment & {
28
+ embeddedFileDict: PDFDict;
29
+ specRef: PDFRef;
30
+ };
31
+ export type UnsavedPDFAttachment = BasePDFAttachment & {
32
+ pdfEmbeddedFile: PDFEmbeddedFile;
33
+ };
34
+ export type PDFAttachment = UnsavedPDFAttachment | SavedPDFAttachment;
26
35
  export type PDFObjectVersions = {
27
36
  ref: PDFRef;
28
37
  actual: PDFObject | undefined;
@@ -575,6 +584,11 @@ export default class PDFDocument {
575
584
  * @returns Array of attachments with name and data
576
585
  */
577
586
  getAttachments(): PDFAttachment[];
587
+ /**
588
+ * Removes an attachment from PDF, based on name.
589
+ * @param {string} name Name of the attachmet to remove.
590
+ */
591
+ detach(name: string): void;
578
592
  /**
579
593
  * Embed a font into this document. The input data can be provided in multiple
580
594
  * formats:
@@ -40,5 +40,11 @@ export default class PDFEmbeddedFile implements Embeddable {
40
40
  * @returns the embedder.
41
41
  */
42
42
  getEmbedder(): FileEmbedder;
43
+ /**
44
+ * Returns whether or not this file has already been embedded.
45
+ * @returns true if the file has already been embedded, false otherwise.
46
+ */
47
+ getAlreadyEmbedded(): boolean;
48
+ getRef(): PDFRef;
43
49
  }
44
50
  //# sourceMappingURL=PDFEmbeddedFile.d.ts.map
@@ -8,7 +8,7 @@ export declare class IncrementalDocumentSnapshot implements DocumentSnapshot {
8
8
  private lastObjectNumber;
9
9
  private changedObjects;
10
10
  context: PDFContext;
11
- constructor(lastObjectNumber: number, indirectObjects: number[], pdfSize: number, prevStartXRef: number, context: PDFContext);
11
+ constructor(lastObjectNumber: number, indirectObjects: Set<number>, pdfSize: number, prevStartXRef: number, context: PDFContext);
12
12
  shouldSave(objectNumber: number): boolean;
13
13
  markRefForSave(ref: PDFRef): void;
14
14
  markRefsForSave(refs: PDFRef[]): void;
@@ -4,11 +4,14 @@ import PDFContext from '../PDFContext';
4
4
  import PDFPageTree from './PDFPageTree';
5
5
  import { PDFAcroForm } from '../acroform';
6
6
  import ViewerPreferences from '../interactive/ViewerPreferences';
7
+ import PDFArray from '../objects/PDFArray';
7
8
  declare class PDFCatalog extends PDFDict {
8
9
  static withContextAndPages: (context: PDFContext, pages: PDFPageTree | PDFRef) => PDFCatalog;
9
10
  static fromMapWithContext: (map: DictMap, context: PDFContext) => PDFCatalog;
10
11
  Pages(): PDFPageTree;
11
12
  AcroForm(): PDFDict | undefined;
13
+ Names(): PDFDict | undefined;
14
+ AttachedFiles(): PDFArray | undefined;
12
15
  getAcroForm(): PDFAcroForm | undefined;
13
16
  getOrCreateAcroForm(): PDFAcroForm;
14
17
  ViewerPreferences(): PDFDict | undefined;
@@ -33,15 +33,23 @@ declare class PDFWriter {
33
33
  * be corrected, to be accurate.
34
34
  */
35
35
  protected _largestSkippedObjectNum: number;
36
+ /**
37
+ * Used to check wheter an object should be saved or not, preserves the object number of the
38
+ * last XRef Stream object, if there is one.
39
+ */
40
+ protected _lastXRefObjectNumber: number;
36
41
  /**
37
42
  * For incremental saves, defers the decision to the snapshot.
38
- * For full saves, checks that the object is not an XRef stream object.
43
+ * For full saves, checks that the object is not the last XRef stream object.
39
44
  * @param {boolean} incremental If making an incremental save, or a full save of the PDF
40
45
  * @param {number} objNum Object number
41
- * @param {PDFObject} object PDFObject used to check if it is an XRef stream, when not 'incremental' saving
46
+ * @param {[PDFRef, PDFObject][]} objects List of objects that form the PDF
42
47
  * @returns {boolean} whether the object should be saved or not
43
48
  */
44
- protected shouldSave(incremental: boolean, objNum: number, object: PDFObject): boolean;
49
+ protected shouldSave(incremental: boolean, objNum: number, objects: [
50
+ PDFRef,
51
+ PDFObject
52
+ ][]): boolean;
45
53
  serializeToBuffer(): Promise<Uint8Array>;
46
54
  protected computeIndirectObjectSize([ref, object]: [
47
55
  PDFRef,