@adnsistemas/pdf-lib 2.7.1 → 2.7.3
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.
- package/README.md +4 -3
- package/cjs/api/PDFDocument.js +1 -1
- package/cjs/api/PDFDocument.js.map +1 -1
- package/cjs/api/snapshot/IncrementalDocumentSnapshot.d.ts +1 -1
- package/cjs/api/snapshot/IncrementalDocumentSnapshot.d.ts.map +1 -1
- package/cjs/api/snapshot/IncrementalDocumentSnapshot.js +3 -7
- package/cjs/api/snapshot/IncrementalDocumentSnapshot.js.map +1 -1
- package/cjs/core/objects/PDFString.js +1 -1
- package/cjs/core/parser/PDFObjectParser.d.ts.map +1 -1
- package/cjs/core/parser/PDFObjectParser.js +2 -1
- package/cjs/core/parser/PDFObjectParser.js.map +1 -1
- package/cjs/core/writers/PDFWriter.d.ts +20 -0
- package/cjs/core/writers/PDFWriter.d.ts.map +1 -1
- package/cjs/core/writers/PDFWriter.js +64 -3
- package/cjs/core/writers/PDFWriter.js.map +1 -1
- package/dist/pdf-lib.esm.js +69 -13
- package/dist/pdf-lib.esm.js.map +1 -1
- package/dist/pdf-lib.esm.min.js +3 -3
- package/dist/pdf-lib.esm.min.js.map +1 -1
- package/dist/pdf-lib.js +69 -13
- package/dist/pdf-lib.js.map +1 -1
- package/dist/pdf-lib.min.js +3 -3
- package/dist/pdf-lib.min.js.map +1 -1
- package/es/api/PDFDocument.js +1 -1
- package/es/api/PDFDocument.js.map +1 -1
- package/es/api/snapshot/IncrementalDocumentSnapshot.d.ts +1 -1
- package/es/api/snapshot/IncrementalDocumentSnapshot.d.ts.map +1 -1
- package/es/api/snapshot/IncrementalDocumentSnapshot.js +3 -7
- package/es/api/snapshot/IncrementalDocumentSnapshot.js.map +1 -1
- package/es/core/objects/PDFString.js +1 -1
- package/es/core/parser/PDFObjectParser.d.ts.map +1 -1
- package/es/core/parser/PDFObjectParser.js +3 -2
- package/es/core/parser/PDFObjectParser.js.map +1 -1
- package/es/core/writers/PDFWriter.d.ts +20 -0
- package/es/core/writers/PDFWriter.d.ts.map +1 -1
- package/es/core/writers/PDFWriter.js +64 -3
- package/es/core/writers/PDFWriter.js.map +1 -1
- package/package.json +1 -1
- package/src/api/PDFDocument.ts +1 -1
- package/src/api/snapshot/IncrementalDocumentSnapshot.ts +5 -11
- package/src/core/objects/PDFString.ts +1 -1
- package/src/core/parser/PDFObjectParser.ts +5 -2
- package/src/core/writers/PDFWriter.ts +72 -3
- package/ts3.4/cjs/api/snapshot/IncrementalDocumentSnapshot.d.ts +1 -1
- package/ts3.4/cjs/core/writers/PDFWriter.d.ts +23 -0
- package/ts3.4/es/api/snapshot/IncrementalDocumentSnapshot.d.ts +1 -1
- package/ts3.4/es/core/writers/PDFWriter.d.ts +23 -0
|
@@ -17,6 +17,8 @@ import { copyStringIntoBuffer, waitForTick } from '../../utils';
|
|
|
17
17
|
import PDFNumber from '../objects/PDFNumber';
|
|
18
18
|
import PDFSecurity from '../security/PDFSecurity';
|
|
19
19
|
import PDFStream from '../objects/PDFStream';
|
|
20
|
+
import PDFName from '../objects/PDFName';
|
|
21
|
+
import PDFRawStream from '../objects/PDFRawStream';
|
|
20
22
|
|
|
21
23
|
export interface SerializationInfo {
|
|
22
24
|
size: number;
|
|
@@ -53,6 +55,61 @@ class PDFWriter {
|
|
|
53
55
|
this.snapshot = snapshot;
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
/**
|
|
59
|
+
* If PDF has an XRef Stream, then the last object will be probably be skipped on saving.
|
|
60
|
+
* If that's the case, this property will have that object number, and the PDF /Size can
|
|
61
|
+
* be corrected, to be accurate.
|
|
62
|
+
*/
|
|
63
|
+
protected _largestSkippedObjectNum: number = 0;
|
|
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;
|
|
70
|
+
/**
|
|
71
|
+
* For incremental saves, defers the decision to the snapshot.
|
|
72
|
+
* For full saves, checks that the object is not the last XRef stream object.
|
|
73
|
+
* @param {boolean} incremental If making an incremental save, or a full save of the PDF
|
|
74
|
+
* @param {number} objNum Object number
|
|
75
|
+
* @param {[PDFRef, PDFObject][]} objects List of objects that form the PDF
|
|
76
|
+
* @returns {boolean} whether the object should be saved or not
|
|
77
|
+
*/
|
|
78
|
+
protected shouldSave(
|
|
79
|
+
incremental: boolean,
|
|
80
|
+
objNum: number,
|
|
81
|
+
objects: [PDFRef, PDFObject][],
|
|
82
|
+
): boolean {
|
|
83
|
+
let should = true;
|
|
84
|
+
if (incremental) {
|
|
85
|
+
should = this.snapshot.shouldSave(objNum);
|
|
86
|
+
} else {
|
|
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;
|
|
107
|
+
}
|
|
108
|
+
if (!should && this._largestSkippedObjectNum < objNum)
|
|
109
|
+
this._largestSkippedObjectNum = objNum;
|
|
110
|
+
return should;
|
|
111
|
+
}
|
|
112
|
+
|
|
56
113
|
async serializeToBuffer(): Promise<Uint8Array> {
|
|
57
114
|
const incremental = !(this.snapshot instanceof DefaultDocumentSnapshot);
|
|
58
115
|
const { size, header, indirectObjects, xref, trailerDict, trailer } =
|
|
@@ -70,7 +127,7 @@ class PDFWriter {
|
|
|
70
127
|
for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
|
|
71
128
|
const [ref, object] = indirectObjects[idx];
|
|
72
129
|
|
|
73
|
-
if (!this.
|
|
130
|
+
if (!this.shouldSave(incremental, ref.objectNumber, indirectObjects)) {
|
|
74
131
|
continue;
|
|
75
132
|
}
|
|
76
133
|
|
|
@@ -130,8 +187,17 @@ class PDFWriter {
|
|
|
130
187
|
}
|
|
131
188
|
|
|
132
189
|
protected createTrailerDict(prevStartXRef?: number): PDFDict {
|
|
190
|
+
/**
|
|
191
|
+
* if last object (XRef Stream) is not in the output, then size is one less.
|
|
192
|
+
* An XRef Stream object should always be the largest object number in PDF
|
|
193
|
+
*/
|
|
194
|
+
const size =
|
|
195
|
+
this.context.largestObjectNumber +
|
|
196
|
+
(this._largestSkippedObjectNum === this.context.largestObjectNumber
|
|
197
|
+
? 0
|
|
198
|
+
: 1);
|
|
133
199
|
return this.context.obj({
|
|
134
|
-
Size:
|
|
200
|
+
Size: size,
|
|
135
201
|
Root: this.context.trailerInfo.Root,
|
|
136
202
|
Encrypt: this.context.trailerInfo.Encrypt,
|
|
137
203
|
Info: this.context.trailerInfo.Info,
|
|
@@ -143,6 +209,8 @@ class PDFWriter {
|
|
|
143
209
|
protected async computeBufferSize(
|
|
144
210
|
incremental: boolean,
|
|
145
211
|
): Promise<SerializationInfo> {
|
|
212
|
+
this._largestSkippedObjectNum = 0;
|
|
213
|
+
this._lastXRefObjectNumber = 0;
|
|
146
214
|
const header = PDFHeader.forVersion(1, 7);
|
|
147
215
|
|
|
148
216
|
let size = this.snapshot.pdfSize;
|
|
@@ -160,7 +228,8 @@ class PDFWriter {
|
|
|
160
228
|
for (let idx = 0, len = indirectObjects.length; idx < len; idx++) {
|
|
161
229
|
const indirectObject = indirectObjects[idx];
|
|
162
230
|
const [ref, object] = indirectObject;
|
|
163
|
-
if (!this.
|
|
231
|
+
if (!this.shouldSave(incremental, ref.objectNumber, indirectObjects))
|
|
232
|
+
continue;
|
|
164
233
|
if (security) this.encrypt(ref, object, security);
|
|
165
234
|
xref.addEntry(ref, size);
|
|
166
235
|
size += this.computeIndirectObjectSize(indirectObject);
|
|
@@ -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
|
|
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;
|
|
@@ -27,6 +27,29 @@ declare class PDFWriter {
|
|
|
27
27
|
protected readonly snapshot: DocumentSnapshot;
|
|
28
28
|
private parsedObjects;
|
|
29
29
|
protected constructor(context: PDFContext, objectsPerTick: number, snapshot: DocumentSnapshot);
|
|
30
|
+
/**
|
|
31
|
+
* If PDF has an XRef Stream, then the last object will be probably be skipped on saving.
|
|
32
|
+
* If that's the case, this property will have that object number, and the PDF /Size can
|
|
33
|
+
* be corrected, to be accurate.
|
|
34
|
+
*/
|
|
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;
|
|
41
|
+
/**
|
|
42
|
+
* For incremental saves, defers the decision to the snapshot.
|
|
43
|
+
* For full saves, checks that the object is not the last XRef stream object.
|
|
44
|
+
* @param {boolean} incremental If making an incremental save, or a full save of the PDF
|
|
45
|
+
* @param {number} objNum Object number
|
|
46
|
+
* @param {[PDFRef, PDFObject][]} objects List of objects that form the PDF
|
|
47
|
+
* @returns {boolean} whether the object should be saved or not
|
|
48
|
+
*/
|
|
49
|
+
protected shouldSave(incremental: boolean, objNum: number, objects: [
|
|
50
|
+
PDFRef,
|
|
51
|
+
PDFObject
|
|
52
|
+
][]): boolean;
|
|
30
53
|
serializeToBuffer(): Promise<Uint8Array>;
|
|
31
54
|
protected computeIndirectObjectSize([ref, object]: [
|
|
32
55
|
PDFRef,
|
|
@@ -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
|
|
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;
|
|
@@ -27,6 +27,29 @@ declare class PDFWriter {
|
|
|
27
27
|
protected readonly snapshot: DocumentSnapshot;
|
|
28
28
|
private parsedObjects;
|
|
29
29
|
protected constructor(context: PDFContext, objectsPerTick: number, snapshot: DocumentSnapshot);
|
|
30
|
+
/**
|
|
31
|
+
* If PDF has an XRef Stream, then the last object will be probably be skipped on saving.
|
|
32
|
+
* If that's the case, this property will have that object number, and the PDF /Size can
|
|
33
|
+
* be corrected, to be accurate.
|
|
34
|
+
*/
|
|
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;
|
|
41
|
+
/**
|
|
42
|
+
* For incremental saves, defers the decision to the snapshot.
|
|
43
|
+
* For full saves, checks that the object is not the last XRef stream object.
|
|
44
|
+
* @param {boolean} incremental If making an incremental save, or a full save of the PDF
|
|
45
|
+
* @param {number} objNum Object number
|
|
46
|
+
* @param {[PDFRef, PDFObject][]} objects List of objects that form the PDF
|
|
47
|
+
* @returns {boolean} whether the object should be saved or not
|
|
48
|
+
*/
|
|
49
|
+
protected shouldSave(incremental: boolean, objNum: number, objects: [
|
|
50
|
+
PDFRef,
|
|
51
|
+
PDFObject
|
|
52
|
+
][]): boolean;
|
|
30
53
|
serializeToBuffer(): Promise<Uint8Array>;
|
|
31
54
|
protected computeIndirectObjectSize([ref, object]: [
|
|
32
55
|
PDFRef,
|