pdf-parser.js 5.2.15 → 5.2.17
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/dist/cff.cjs +1 -2
- package/dist/cff.js +1 -2
- package/dist/write.cjs +52 -54
- package/dist/write.js +52 -54
- package/package.json +1 -1
package/dist/cff.cjs
CHANGED
|
@@ -32,7 +32,6 @@ const REAL_NIBBLE_DECIMAL_POINT = 10;
|
|
|
32
32
|
const REAL_NIBBLE_EXPONENT = 11;
|
|
33
33
|
const REAL_NIBBLE_NEGATIVE_EXPONENT = 12;
|
|
34
34
|
const REAL_NIBBLE_RESERVED = 13;
|
|
35
|
-
const REAL_NIBBLE_MINUS = 14;
|
|
36
35
|
const REAL_NIBBLE_TERMINATOR = 15;
|
|
37
36
|
const NIBBLES_PER_BYTE = 2;
|
|
38
37
|
const HIGH_NIBBLE_SHIFT = 4;
|
|
@@ -85,7 +84,7 @@ function readRealOperand(data, start) {
|
|
|
85
84
|
else if (nibble === REAL_NIBBLE_DECIMAL_POINT) text += ".";
|
|
86
85
|
else if (nibble === REAL_NIBBLE_EXPONENT) text += "E";
|
|
87
86
|
else if (nibble === REAL_NIBBLE_NEGATIVE_EXPONENT) text += "E-";
|
|
88
|
-
else
|
|
87
|
+
else text += "-";
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
}
|
package/dist/cff.js
CHANGED
|
@@ -31,7 +31,6 @@ const REAL_NIBBLE_DECIMAL_POINT = 10;
|
|
|
31
31
|
const REAL_NIBBLE_EXPONENT = 11;
|
|
32
32
|
const REAL_NIBBLE_NEGATIVE_EXPONENT = 12;
|
|
33
33
|
const REAL_NIBBLE_RESERVED = 13;
|
|
34
|
-
const REAL_NIBBLE_MINUS = 14;
|
|
35
34
|
const REAL_NIBBLE_TERMINATOR = 15;
|
|
36
35
|
const NIBBLES_PER_BYTE = 2;
|
|
37
36
|
const HIGH_NIBBLE_SHIFT = 4;
|
|
@@ -84,7 +83,7 @@ function readRealOperand(data, start) {
|
|
|
84
83
|
else if (nibble === REAL_NIBBLE_DECIMAL_POINT) text += ".";
|
|
85
84
|
else if (nibble === REAL_NIBBLE_EXPONENT) text += "E";
|
|
86
85
|
else if (nibble === REAL_NIBBLE_NEGATIVE_EXPONENT) text += "E-";
|
|
87
|
-
else
|
|
86
|
+
else text += "-";
|
|
88
87
|
}
|
|
89
88
|
}
|
|
90
89
|
}
|
package/dist/write.cjs
CHANGED
|
@@ -40,10 +40,12 @@ function textToPdfString(text) {
|
|
|
40
40
|
const bytes = new Uint8Array(2 + text.length * 2);
|
|
41
41
|
bytes[0] = 254;
|
|
42
42
|
bytes[1] = 255;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
bytes[
|
|
43
|
+
let offset = 2;
|
|
44
|
+
for (const unit of text.split("")) {
|
|
45
|
+
const code = unit.charCodeAt(0);
|
|
46
|
+
bytes[offset] = code >> 8 & 255;
|
|
47
|
+
bytes[offset + 1] = code & 255;
|
|
48
|
+
offset += 2;
|
|
47
49
|
}
|
|
48
50
|
return require_objects.pdfHexString(bytes);
|
|
49
51
|
}
|
|
@@ -103,6 +105,9 @@ function buildFontObjects(standardName, descriptorRef) {
|
|
|
103
105
|
})
|
|
104
106
|
};
|
|
105
107
|
}
|
|
108
|
+
function codePointsOf(texts) {
|
|
109
|
+
return new Set(texts.flatMap((text) => [...text].map((character) => character.codePointAt(0))));
|
|
110
|
+
}
|
|
106
111
|
function prepareJpegImage(bytes) {
|
|
107
112
|
const info = require_image_jpeg_info.readJpegInfo(bytes);
|
|
108
113
|
const colorSpace = info.components === 1 ? "DeviceGray" : info.components === 4 ? "DeviceCMYK" : "DeviceRGB";
|
|
@@ -145,12 +150,14 @@ function pngImageDict(width, height, colorSpace, compress) {
|
|
|
145
150
|
function packBilevel(raw) {
|
|
146
151
|
const rowBytes = raw.width + 7 >> 3;
|
|
147
152
|
const packed = new Uint8Array(rowBytes * raw.height);
|
|
148
|
-
|
|
149
|
-
|
|
153
|
+
const view = new DataView(packed.buffer);
|
|
154
|
+
for (let index = 0; index < raw.data.length; index++) {
|
|
155
|
+
const sample = raw.data[index];
|
|
150
156
|
if (sample !== 0 && sample !== 255) return;
|
|
151
157
|
if (sample === 255) {
|
|
152
|
-
const
|
|
153
|
-
|
|
158
|
+
const x = index % raw.width;
|
|
159
|
+
const byteIndex = Math.floor(index / raw.width) * rowBytes + (x >> 3);
|
|
160
|
+
view.setUint8(byteIndex, view.getUint8(byteIndex) | 128 >> (x & 7));
|
|
154
161
|
}
|
|
155
162
|
}
|
|
156
163
|
return packed;
|
|
@@ -202,28 +209,27 @@ function preparePngImage(bytes, compress) {
|
|
|
202
209
|
}
|
|
203
210
|
};
|
|
204
211
|
}
|
|
205
|
-
function preparePassthroughImage(asset, compress) {
|
|
206
|
-
if (asset.original === void 0) throw new Error("preparePassthroughImage: asset carries no original stream");
|
|
212
|
+
function preparePassthroughImage(asset, original, compress) {
|
|
207
213
|
const png = preparePngImage((0, byte_codec.base64ToBytes)(asset.base64), compress);
|
|
208
214
|
const entries = /* @__PURE__ */ new Map([
|
|
209
215
|
["Type", require_objects.pdfName("XObject")],
|
|
210
216
|
["Subtype", require_objects.pdfName("Image")],
|
|
211
217
|
["Width", require_objects.pdfNum(asset.widthPx)],
|
|
212
218
|
["Height", require_objects.pdfNum(asset.heightPx)],
|
|
213
|
-
["Filter", require_objects.pdfName(
|
|
219
|
+
["Filter", require_objects.pdfName(original.filter === "jbig2" ? "JBIG2Decode" : "JPXDecode")]
|
|
214
220
|
]);
|
|
215
|
-
if (
|
|
221
|
+
if (original.filter === "jbig2") {
|
|
216
222
|
entries.set("ColorSpace", require_objects.pdfName("DeviceGray"));
|
|
217
223
|
entries.set("BitsPerComponent", require_objects.pdfNum(1));
|
|
218
224
|
}
|
|
219
225
|
return {
|
|
220
226
|
dict: require_objects.pdfDict(entries),
|
|
221
|
-
raw: (0, byte_codec.base64ToBytes)(
|
|
222
|
-
|
|
227
|
+
raw: (0, byte_codec.base64ToBytes)(original.base64),
|
|
228
|
+
alpha: png.alpha
|
|
223
229
|
};
|
|
224
230
|
}
|
|
225
231
|
function prepareImage(asset, compress) {
|
|
226
|
-
if (asset.original !== void 0) return preparePassthroughImage(asset, compress);
|
|
232
|
+
if (asset.original !== void 0) return preparePassthroughImage(asset, asset.original, compress);
|
|
227
233
|
const bytes = (0, byte_codec.base64ToBytes)(asset.base64);
|
|
228
234
|
return asset.format === "jpeg" ? prepareJpegImage(bytes) : preparePngImage(bytes, compress);
|
|
229
235
|
}
|
|
@@ -322,7 +328,7 @@ function xrefEntry(offset, generation, inUse) {
|
|
|
322
328
|
}
|
|
323
329
|
function parseResidueRow(residue) {
|
|
324
330
|
const reader = new require_bytes_reader.ByteReader(new TextEncoder().encode(residue.xml));
|
|
325
|
-
return require_parse.parseValue(reader, () =>
|
|
331
|
+
return require_parse.parseValue(reader, () => void 0);
|
|
326
332
|
}
|
|
327
333
|
function objectContainsReference(obj) {
|
|
328
334
|
if (obj.kind === "ref") return true;
|
|
@@ -352,13 +358,9 @@ function writePdf(doc, options = {}) {
|
|
|
352
358
|
for (const page of doc.pages) for (const item of page.items) if (item.kind === "text") {
|
|
353
359
|
const resolved = require_font_registry.resolveFaceWithRegistry(registry, item.font);
|
|
354
360
|
if (resolved.kind === "embedded") {
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
};
|
|
359
|
-
use.texts.push(item.text);
|
|
360
|
-
for (const character of item.text) use.codePoints.add(character.codePointAt(0));
|
|
361
|
-
embeddedUses.set(resolved.face, use);
|
|
361
|
+
const texts = embeddedUses.get(resolved.face) ?? [];
|
|
362
|
+
texts.push(item.text);
|
|
363
|
+
embeddedUses.set(resolved.face, texts);
|
|
362
364
|
} else fontNames.add(resolved.standardName);
|
|
363
365
|
} else if (item.kind === "image") imageIds.add(item.imageId);
|
|
364
366
|
const fontAllocs = /* @__PURE__ */ new Map();
|
|
@@ -400,15 +402,15 @@ function writePdf(doc, options = {}) {
|
|
|
400
402
|
};
|
|
401
403
|
const embeddedAllocs = /* @__PURE__ */ new Map();
|
|
402
404
|
const sortedEmbeddedUses = [...embeddedUses.entries()].sort(([a], [b]) => a.postScriptName < b.postScriptName ? -1 : a.postScriptName > b.postScriptName ? 1 : 0);
|
|
403
|
-
for (const [index, [face,
|
|
405
|
+
for (const [index, [face, texts]] of sortedEmbeddedUses.entries()) embeddedAllocs.set(face, {
|
|
404
406
|
type0Num: nextObjNum++,
|
|
405
407
|
cidFontNum: nextObjNum++,
|
|
406
408
|
descriptorNum: nextObjNum++,
|
|
407
409
|
fontFileNum: nextObjNum++,
|
|
408
410
|
toUnicodeNum: nextObjNum++,
|
|
409
411
|
resourceName: `${EMBEDDED_FONT_RESOURCE_PREFIX}${index + 1}`,
|
|
410
|
-
texts
|
|
411
|
-
codePoints:
|
|
412
|
+
texts,
|
|
413
|
+
codePoints: codePointsOf(texts)
|
|
412
414
|
});
|
|
413
415
|
const pageAllocs = doc.pages.map(() => ({
|
|
414
416
|
pageNum: nextObjNum++,
|
|
@@ -422,14 +424,12 @@ function writePdf(doc, options = {}) {
|
|
|
422
424
|
const attachmentsNamesNum = attachmentAllocs.length > 0 ? nextObjNum++ : void 0;
|
|
423
425
|
const outlineRootNum = (doc.outline ?? []).length > 0 ? nextObjNum++ : void 0;
|
|
424
426
|
const outlineItemNums = [];
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
for (let i = 0; i < countItems(doc.outline ?? []); i += 1) outlineItemNums.push(nextObjNum++);
|
|
432
|
-
}
|
|
427
|
+
const countItems = (items) => {
|
|
428
|
+
let n = 0;
|
|
429
|
+
for (const item of items) n += 1 + countItems(item.children);
|
|
430
|
+
return n;
|
|
431
|
+
};
|
|
432
|
+
for (let i = 0; i < countItems(doc.outline ?? []); i += 1) outlineItemNums.push(nextObjNum++);
|
|
433
433
|
const layerNumByName = /* @__PURE__ */ new Map();
|
|
434
434
|
for (const layer of doc.layers ?? []) layerNumByName.set(layer.name, nextObjNum++);
|
|
435
435
|
const formObjectNums = [];
|
|
@@ -456,17 +456,15 @@ function writePdf(doc, options = {}) {
|
|
|
456
456
|
return num;
|
|
457
457
|
};
|
|
458
458
|
const structElementNumById = /* @__PURE__ */ new Map();
|
|
459
|
-
const
|
|
460
|
-
let n = 0;
|
|
459
|
+
const allocateStructureElements = (elements) => {
|
|
461
460
|
for (const element of elements) {
|
|
462
461
|
structElementNumById.set(element.id, nextObjNum++);
|
|
463
|
-
|
|
462
|
+
allocateStructureElements(element.children);
|
|
464
463
|
}
|
|
465
|
-
return n;
|
|
466
464
|
};
|
|
467
|
-
|
|
468
|
-
const structRootNum =
|
|
469
|
-
const structParentTreeNum =
|
|
465
|
+
allocateStructureElements(doc.structure ?? []);
|
|
466
|
+
const structRootNum = structElementNumById.size > 0 ? nextObjNum++ : void 0;
|
|
467
|
+
const structParentTreeNum = structElementNumById.size > 0 ? nextObjNum++ : void 0;
|
|
470
468
|
const residueXmpNum = doc.source?.xmp !== void 0 ? nextObjNum++ : void 0;
|
|
471
469
|
const objects = [];
|
|
472
470
|
const catalogEntries = [["Type", require_objects.pdfName("Catalog")], ["Pages", require_objects.pdfRef(pagesNum, 0)]];
|
|
@@ -550,7 +548,7 @@ function writePdf(doc, options = {}) {
|
|
|
550
548
|
value: require_objects.pdfDict({ EmbeddedFiles: require_objects.pdfDict({ Names: require_objects.pdfArray(names) }) })
|
|
551
549
|
});
|
|
552
550
|
}
|
|
553
|
-
if (outlineRootNum !== void 0
|
|
551
|
+
if (outlineRootNum !== void 0) {
|
|
554
552
|
let itemCursor = 0;
|
|
555
553
|
const emitItems = (items, parentNum) => {
|
|
556
554
|
const siblingNums = [];
|
|
@@ -625,7 +623,7 @@ function writePdf(doc, options = {}) {
|
|
|
625
623
|
};
|
|
626
624
|
const emitFormFieldObjects = (fields, parentName) => {
|
|
627
625
|
for (const field of fields) {
|
|
628
|
-
const ownName = parentName
|
|
626
|
+
const ownName = parentName === void 0 ? field.name : field.name.startsWith(`${parentName}.`) ? field.name.slice(parentName.length + 1) : field.name;
|
|
629
627
|
const entries = [];
|
|
630
628
|
if (ownName.length > 0) entries.push(["T", require_objects.pdfLiteralString(new TextEncoder().encode(ownName))]);
|
|
631
629
|
if (field.alias !== void 0) entries.push(["TU", require_objects.pdfLiteralString(new TextEncoder().encode(field.alias))]);
|
|
@@ -644,7 +642,7 @@ function writePdf(doc, options = {}) {
|
|
|
644
642
|
if (flags !== 0) entries.push(["Ff", require_objects.pdfNum(flags)]);
|
|
645
643
|
if (field.fieldType === "text" || field.fieldType === "listbox" || field.fieldType === "combobox") {
|
|
646
644
|
if (field.value !== void 0) entries.push(["V", require_objects.pdfLiteralString(new TextEncoder().encode(field.value))]);
|
|
647
|
-
} else if (field.fieldType === "checkbox" || field.fieldType === "radio") entries.push(["V", require_objects.pdfName(field.
|
|
645
|
+
} else if (field.fieldType === "checkbox" || field.fieldType === "radio") entries.push(["V", require_objects.pdfName(field.value ?? (field.checked === true ? "Yes" : "Off"))]);
|
|
648
646
|
if (field.options !== void 0) entries.push(["Opt", require_objects.pdfArray(field.options.map((option) => require_objects.pdfLiteralString(new TextEncoder().encode(option))))]);
|
|
649
647
|
const firstWidget = field.widgets[0];
|
|
650
648
|
if (field.widgets.length === 1 && firstWidget !== void 0) {
|
|
@@ -652,7 +650,7 @@ function writePdf(doc, options = {}) {
|
|
|
652
650
|
entries.push(["Rect", widgetRectArray(firstWidget)]);
|
|
653
651
|
entries.push(["P", require_objects.pdfRef(pageAllocs[firstWidget.pageIndex].pageNum, 0)]);
|
|
654
652
|
noteWidgetAnnot(firstWidget, require_objects.pdfRef(formNumOf(field), 0));
|
|
655
|
-
} else if (field
|
|
653
|
+
} else if (formExtraWidgetNums.has(field)) {
|
|
656
654
|
const extraNums = formExtraWidgetNums.get(field) ?? [];
|
|
657
655
|
entries.push(["Kids", require_objects.pdfArray(extraNums.map((num) => require_objects.pdfRef(num, 0)))]);
|
|
658
656
|
for (const [index, num] of extraNums.entries()) {
|
|
@@ -676,8 +674,8 @@ function writePdf(doc, options = {}) {
|
|
|
676
674
|
emitFormFieldObjects(field.children, field.name);
|
|
677
675
|
}
|
|
678
676
|
};
|
|
679
|
-
emitFormFieldObjects(doc.form ?? [],
|
|
680
|
-
if (structRootNum !== void 0
|
|
677
|
+
emitFormFieldObjects(doc.form ?? [], void 0);
|
|
678
|
+
if (structRootNum !== void 0) {
|
|
681
679
|
const emitStructureElement = (element, parentNum) => {
|
|
682
680
|
const entries = [
|
|
683
681
|
["Type", require_objects.pdfName("StructElem")],
|
|
@@ -774,7 +772,7 @@ function writePdf(doc, options = {}) {
|
|
|
774
772
|
}
|
|
775
773
|
for (const [face, alloc] of embeddedAllocs) {
|
|
776
774
|
const usedGlyphs = require_embedded_font.collectEmbeddedGlyphs(alloc.texts, face);
|
|
777
|
-
const subset = require_sfnt_subset.subsetSfnt(face.font, [...alloc.codePoints]
|
|
775
|
+
const subset = require_sfnt_subset.subsetSfnt(face.font, [...alloc.codePoints], [...usedGlyphs.keys()]);
|
|
778
776
|
if (subset === void 0) throw new Error(`font "${face.postScriptName}" resolved to an embeddable face, but its glyph outlines could not be subsetted — only TrueType-outline ('glyf') fonts can be embedded, so supply a TrueType face for this family or drop it from the registry`);
|
|
779
777
|
const built = require_embedded_font_write.buildEmbeddedFontObjects(face, subset, usedGlyphs, {
|
|
780
778
|
cidFontRef: require_objects.pdfRef(alloc.cidFontNum, 0),
|
|
@@ -887,7 +885,7 @@ function writePdf(doc, options = {}) {
|
|
|
887
885
|
["Contents", require_objects.pdfRef(contentsNum, 0)]
|
|
888
886
|
]);
|
|
889
887
|
if (annots.length > 0) pageEntries.set("Annots", require_objects.pdfArray(annots));
|
|
890
|
-
if (
|
|
888
|
+
if (markedStructureByPage.has(pageIndex)) pageEntries.set("StructParents", require_objects.pdfNum(pageIndex));
|
|
891
889
|
objects.push({
|
|
892
890
|
num: pageNum,
|
|
893
891
|
value: require_objects.pdfDict(pageEntries)
|
|
@@ -897,11 +895,11 @@ function writePdf(doc, options = {}) {
|
|
|
897
895
|
const nums = [];
|
|
898
896
|
for (const [pageIndex, marks] of markedStructureByPage) {
|
|
899
897
|
const maxMcid = Math.max(...marks.map((mark) => mark.mcid));
|
|
900
|
-
const byMcid = Array.from({ length: maxMcid + 1 }, () =>
|
|
901
|
-
|
|
902
|
-
const elementNum = structElementNumById.get(mark.structureId);
|
|
903
|
-
|
|
904
|
-
}
|
|
898
|
+
const byMcid = Array.from({ length: maxMcid + 1 }, (_, mcid) => {
|
|
899
|
+
const mark = marks.find((candidate) => candidate.mcid === mcid);
|
|
900
|
+
const elementNum = mark === void 0 ? void 0 : structElementNumById.get(mark.structureId);
|
|
901
|
+
return elementNum === void 0 ? require_objects.pdfNull() : require_objects.pdfRef(elementNum, 0);
|
|
902
|
+
});
|
|
905
903
|
nums.push(require_objects.pdfNum(pageIndex), require_objects.pdfArray(byMcid));
|
|
906
904
|
}
|
|
907
905
|
objects.push({
|
package/dist/write.js
CHANGED
|
@@ -39,10 +39,12 @@ function textToPdfString(text) {
|
|
|
39
39
|
const bytes = new Uint8Array(2 + text.length * 2);
|
|
40
40
|
bytes[0] = 254;
|
|
41
41
|
bytes[1] = 255;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
bytes[
|
|
42
|
+
let offset = 2;
|
|
43
|
+
for (const unit of text.split("")) {
|
|
44
|
+
const code = unit.charCodeAt(0);
|
|
45
|
+
bytes[offset] = code >> 8 & 255;
|
|
46
|
+
bytes[offset + 1] = code & 255;
|
|
47
|
+
offset += 2;
|
|
46
48
|
}
|
|
47
49
|
return pdfHexString(bytes);
|
|
48
50
|
}
|
|
@@ -102,6 +104,9 @@ function buildFontObjects(standardName, descriptorRef) {
|
|
|
102
104
|
})
|
|
103
105
|
};
|
|
104
106
|
}
|
|
107
|
+
function codePointsOf(texts) {
|
|
108
|
+
return new Set(texts.flatMap((text) => [...text].map((character) => character.codePointAt(0))));
|
|
109
|
+
}
|
|
105
110
|
function prepareJpegImage(bytes) {
|
|
106
111
|
const info = readJpegInfo$1(bytes);
|
|
107
112
|
const colorSpace = info.components === 1 ? "DeviceGray" : info.components === 4 ? "DeviceCMYK" : "DeviceRGB";
|
|
@@ -144,12 +149,14 @@ function pngImageDict(width, height, colorSpace, compress) {
|
|
|
144
149
|
function packBilevel(raw) {
|
|
145
150
|
const rowBytes = raw.width + 7 >> 3;
|
|
146
151
|
const packed = new Uint8Array(rowBytes * raw.height);
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
const view = new DataView(packed.buffer);
|
|
153
|
+
for (let index = 0; index < raw.data.length; index++) {
|
|
154
|
+
const sample = raw.data[index];
|
|
149
155
|
if (sample !== 0 && sample !== 255) return;
|
|
150
156
|
if (sample === 255) {
|
|
151
|
-
const
|
|
152
|
-
|
|
157
|
+
const x = index % raw.width;
|
|
158
|
+
const byteIndex = Math.floor(index / raw.width) * rowBytes + (x >> 3);
|
|
159
|
+
view.setUint8(byteIndex, view.getUint8(byteIndex) | 128 >> (x & 7));
|
|
153
160
|
}
|
|
154
161
|
}
|
|
155
162
|
return packed;
|
|
@@ -201,28 +208,27 @@ function preparePngImage(bytes, compress) {
|
|
|
201
208
|
}
|
|
202
209
|
};
|
|
203
210
|
}
|
|
204
|
-
function preparePassthroughImage(asset, compress) {
|
|
205
|
-
if (asset.original === void 0) throw new Error("preparePassthroughImage: asset carries no original stream");
|
|
211
|
+
function preparePassthroughImage(asset, original, compress) {
|
|
206
212
|
const png = preparePngImage(base64ToBytes(asset.base64), compress);
|
|
207
213
|
const entries = /* @__PURE__ */ new Map([
|
|
208
214
|
["Type", pdfName("XObject")],
|
|
209
215
|
["Subtype", pdfName("Image")],
|
|
210
216
|
["Width", pdfNum(asset.widthPx)],
|
|
211
217
|
["Height", pdfNum(asset.heightPx)],
|
|
212
|
-
["Filter", pdfName(
|
|
218
|
+
["Filter", pdfName(original.filter === "jbig2" ? "JBIG2Decode" : "JPXDecode")]
|
|
213
219
|
]);
|
|
214
|
-
if (
|
|
220
|
+
if (original.filter === "jbig2") {
|
|
215
221
|
entries.set("ColorSpace", pdfName("DeviceGray"));
|
|
216
222
|
entries.set("BitsPerComponent", pdfNum(1));
|
|
217
223
|
}
|
|
218
224
|
return {
|
|
219
225
|
dict: pdfDict(entries),
|
|
220
|
-
raw: base64ToBytes(
|
|
221
|
-
|
|
226
|
+
raw: base64ToBytes(original.base64),
|
|
227
|
+
alpha: png.alpha
|
|
222
228
|
};
|
|
223
229
|
}
|
|
224
230
|
function prepareImage(asset, compress) {
|
|
225
|
-
if (asset.original !== void 0) return preparePassthroughImage(asset, compress);
|
|
231
|
+
if (asset.original !== void 0) return preparePassthroughImage(asset, asset.original, compress);
|
|
226
232
|
const bytes = base64ToBytes(asset.base64);
|
|
227
233
|
return asset.format === "jpeg" ? prepareJpegImage(bytes) : preparePngImage(bytes, compress);
|
|
228
234
|
}
|
|
@@ -321,7 +327,7 @@ function xrefEntry(offset, generation, inUse) {
|
|
|
321
327
|
}
|
|
322
328
|
function parseResidueRow(residue) {
|
|
323
329
|
const reader = new ByteReader(new TextEncoder().encode(residue.xml));
|
|
324
|
-
return parseValue(reader, () =>
|
|
330
|
+
return parseValue(reader, () => void 0);
|
|
325
331
|
}
|
|
326
332
|
function objectContainsReference(obj) {
|
|
327
333
|
if (obj.kind === "ref") return true;
|
|
@@ -351,13 +357,9 @@ function writePdf(doc, options = {}) {
|
|
|
351
357
|
for (const page of doc.pages) for (const item of page.items) if (item.kind === "text") {
|
|
352
358
|
const resolved = resolveFaceWithRegistry(registry, item.font);
|
|
353
359
|
if (resolved.kind === "embedded") {
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
};
|
|
358
|
-
use.texts.push(item.text);
|
|
359
|
-
for (const character of item.text) use.codePoints.add(character.codePointAt(0));
|
|
360
|
-
embeddedUses.set(resolved.face, use);
|
|
360
|
+
const texts = embeddedUses.get(resolved.face) ?? [];
|
|
361
|
+
texts.push(item.text);
|
|
362
|
+
embeddedUses.set(resolved.face, texts);
|
|
361
363
|
} else fontNames.add(resolved.standardName);
|
|
362
364
|
} else if (item.kind === "image") imageIds.add(item.imageId);
|
|
363
365
|
const fontAllocs = /* @__PURE__ */ new Map();
|
|
@@ -399,15 +401,15 @@ function writePdf(doc, options = {}) {
|
|
|
399
401
|
};
|
|
400
402
|
const embeddedAllocs = /* @__PURE__ */ new Map();
|
|
401
403
|
const sortedEmbeddedUses = [...embeddedUses.entries()].sort(([a], [b]) => a.postScriptName < b.postScriptName ? -1 : a.postScriptName > b.postScriptName ? 1 : 0);
|
|
402
|
-
for (const [index, [face,
|
|
404
|
+
for (const [index, [face, texts]] of sortedEmbeddedUses.entries()) embeddedAllocs.set(face, {
|
|
403
405
|
type0Num: nextObjNum++,
|
|
404
406
|
cidFontNum: nextObjNum++,
|
|
405
407
|
descriptorNum: nextObjNum++,
|
|
406
408
|
fontFileNum: nextObjNum++,
|
|
407
409
|
toUnicodeNum: nextObjNum++,
|
|
408
410
|
resourceName: `${EMBEDDED_FONT_RESOURCE_PREFIX}${index + 1}`,
|
|
409
|
-
texts
|
|
410
|
-
codePoints:
|
|
411
|
+
texts,
|
|
412
|
+
codePoints: codePointsOf(texts)
|
|
411
413
|
});
|
|
412
414
|
const pageAllocs = doc.pages.map(() => ({
|
|
413
415
|
pageNum: nextObjNum++,
|
|
@@ -421,14 +423,12 @@ function writePdf(doc, options = {}) {
|
|
|
421
423
|
const attachmentsNamesNum = attachmentAllocs.length > 0 ? nextObjNum++ : void 0;
|
|
422
424
|
const outlineRootNum = (doc.outline ?? []).length > 0 ? nextObjNum++ : void 0;
|
|
423
425
|
const outlineItemNums = [];
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
for (let i = 0; i < countItems(doc.outline ?? []); i += 1) outlineItemNums.push(nextObjNum++);
|
|
431
|
-
}
|
|
426
|
+
const countItems = (items) => {
|
|
427
|
+
let n = 0;
|
|
428
|
+
for (const item of items) n += 1 + countItems(item.children);
|
|
429
|
+
return n;
|
|
430
|
+
};
|
|
431
|
+
for (let i = 0; i < countItems(doc.outline ?? []); i += 1) outlineItemNums.push(nextObjNum++);
|
|
432
432
|
const layerNumByName = /* @__PURE__ */ new Map();
|
|
433
433
|
for (const layer of doc.layers ?? []) layerNumByName.set(layer.name, nextObjNum++);
|
|
434
434
|
const formObjectNums = [];
|
|
@@ -455,17 +455,15 @@ function writePdf(doc, options = {}) {
|
|
|
455
455
|
return num;
|
|
456
456
|
};
|
|
457
457
|
const structElementNumById = /* @__PURE__ */ new Map();
|
|
458
|
-
const
|
|
459
|
-
let n = 0;
|
|
458
|
+
const allocateStructureElements = (elements) => {
|
|
460
459
|
for (const element of elements) {
|
|
461
460
|
structElementNumById.set(element.id, nextObjNum++);
|
|
462
|
-
|
|
461
|
+
allocateStructureElements(element.children);
|
|
463
462
|
}
|
|
464
|
-
return n;
|
|
465
463
|
};
|
|
466
|
-
|
|
467
|
-
const structRootNum =
|
|
468
|
-
const structParentTreeNum =
|
|
464
|
+
allocateStructureElements(doc.structure ?? []);
|
|
465
|
+
const structRootNum = structElementNumById.size > 0 ? nextObjNum++ : void 0;
|
|
466
|
+
const structParentTreeNum = structElementNumById.size > 0 ? nextObjNum++ : void 0;
|
|
469
467
|
const residueXmpNum = doc.source?.xmp !== void 0 ? nextObjNum++ : void 0;
|
|
470
468
|
const objects = [];
|
|
471
469
|
const catalogEntries = [["Type", pdfName("Catalog")], ["Pages", pdfRef(pagesNum, 0)]];
|
|
@@ -549,7 +547,7 @@ function writePdf(doc, options = {}) {
|
|
|
549
547
|
value: pdfDict({ EmbeddedFiles: pdfDict({ Names: pdfArray(names) }) })
|
|
550
548
|
});
|
|
551
549
|
}
|
|
552
|
-
if (outlineRootNum !== void 0
|
|
550
|
+
if (outlineRootNum !== void 0) {
|
|
553
551
|
let itemCursor = 0;
|
|
554
552
|
const emitItems = (items, parentNum) => {
|
|
555
553
|
const siblingNums = [];
|
|
@@ -624,7 +622,7 @@ function writePdf(doc, options = {}) {
|
|
|
624
622
|
};
|
|
625
623
|
const emitFormFieldObjects = (fields, parentName) => {
|
|
626
624
|
for (const field of fields) {
|
|
627
|
-
const ownName = parentName
|
|
625
|
+
const ownName = parentName === void 0 ? field.name : field.name.startsWith(`${parentName}.`) ? field.name.slice(parentName.length + 1) : field.name;
|
|
628
626
|
const entries = [];
|
|
629
627
|
if (ownName.length > 0) entries.push(["T", pdfLiteralString(new TextEncoder().encode(ownName))]);
|
|
630
628
|
if (field.alias !== void 0) entries.push(["TU", pdfLiteralString(new TextEncoder().encode(field.alias))]);
|
|
@@ -643,7 +641,7 @@ function writePdf(doc, options = {}) {
|
|
|
643
641
|
if (flags !== 0) entries.push(["Ff", pdfNum(flags)]);
|
|
644
642
|
if (field.fieldType === "text" || field.fieldType === "listbox" || field.fieldType === "combobox") {
|
|
645
643
|
if (field.value !== void 0) entries.push(["V", pdfLiteralString(new TextEncoder().encode(field.value))]);
|
|
646
|
-
} else if (field.fieldType === "checkbox" || field.fieldType === "radio") entries.push(["V", pdfName(field.
|
|
644
|
+
} else if (field.fieldType === "checkbox" || field.fieldType === "radio") entries.push(["V", pdfName(field.value ?? (field.checked === true ? "Yes" : "Off"))]);
|
|
647
645
|
if (field.options !== void 0) entries.push(["Opt", pdfArray(field.options.map((option) => pdfLiteralString(new TextEncoder().encode(option))))]);
|
|
648
646
|
const firstWidget = field.widgets[0];
|
|
649
647
|
if (field.widgets.length === 1 && firstWidget !== void 0) {
|
|
@@ -651,7 +649,7 @@ function writePdf(doc, options = {}) {
|
|
|
651
649
|
entries.push(["Rect", widgetRectArray(firstWidget)]);
|
|
652
650
|
entries.push(["P", pdfRef(pageAllocs[firstWidget.pageIndex].pageNum, 0)]);
|
|
653
651
|
noteWidgetAnnot(firstWidget, pdfRef(formNumOf(field), 0));
|
|
654
|
-
} else if (field
|
|
652
|
+
} else if (formExtraWidgetNums.has(field)) {
|
|
655
653
|
const extraNums = formExtraWidgetNums.get(field) ?? [];
|
|
656
654
|
entries.push(["Kids", pdfArray(extraNums.map((num) => pdfRef(num, 0)))]);
|
|
657
655
|
for (const [index, num] of extraNums.entries()) {
|
|
@@ -675,8 +673,8 @@ function writePdf(doc, options = {}) {
|
|
|
675
673
|
emitFormFieldObjects(field.children, field.name);
|
|
676
674
|
}
|
|
677
675
|
};
|
|
678
|
-
emitFormFieldObjects(doc.form ?? [],
|
|
679
|
-
if (structRootNum !== void 0
|
|
676
|
+
emitFormFieldObjects(doc.form ?? [], void 0);
|
|
677
|
+
if (structRootNum !== void 0) {
|
|
680
678
|
const emitStructureElement = (element, parentNum) => {
|
|
681
679
|
const entries = [
|
|
682
680
|
["Type", pdfName("StructElem")],
|
|
@@ -773,7 +771,7 @@ function writePdf(doc, options = {}) {
|
|
|
773
771
|
}
|
|
774
772
|
for (const [face, alloc] of embeddedAllocs) {
|
|
775
773
|
const usedGlyphs = collectEmbeddedGlyphs(alloc.texts, face);
|
|
776
|
-
const subset = subsetSfnt(face.font, [...alloc.codePoints]
|
|
774
|
+
const subset = subsetSfnt(face.font, [...alloc.codePoints], [...usedGlyphs.keys()]);
|
|
777
775
|
if (subset === void 0) throw new Error(`font "${face.postScriptName}" resolved to an embeddable face, but its glyph outlines could not be subsetted — only TrueType-outline ('glyf') fonts can be embedded, so supply a TrueType face for this family or drop it from the registry`);
|
|
778
776
|
const built = buildEmbeddedFontObjects(face, subset, usedGlyphs, {
|
|
779
777
|
cidFontRef: pdfRef(alloc.cidFontNum, 0),
|
|
@@ -886,7 +884,7 @@ function writePdf(doc, options = {}) {
|
|
|
886
884
|
["Contents", pdfRef(contentsNum, 0)]
|
|
887
885
|
]);
|
|
888
886
|
if (annots.length > 0) pageEntries.set("Annots", pdfArray(annots));
|
|
889
|
-
if (
|
|
887
|
+
if (markedStructureByPage.has(pageIndex)) pageEntries.set("StructParents", pdfNum(pageIndex));
|
|
890
888
|
objects.push({
|
|
891
889
|
num: pageNum,
|
|
892
890
|
value: pdfDict(pageEntries)
|
|
@@ -896,11 +894,11 @@ function writePdf(doc, options = {}) {
|
|
|
896
894
|
const nums = [];
|
|
897
895
|
for (const [pageIndex, marks] of markedStructureByPage) {
|
|
898
896
|
const maxMcid = Math.max(...marks.map((mark) => mark.mcid));
|
|
899
|
-
const byMcid = Array.from({ length: maxMcid + 1 }, () =>
|
|
900
|
-
|
|
901
|
-
const elementNum = structElementNumById.get(mark.structureId);
|
|
902
|
-
|
|
903
|
-
}
|
|
897
|
+
const byMcid = Array.from({ length: maxMcid + 1 }, (_, mcid) => {
|
|
898
|
+
const mark = marks.find((candidate) => candidate.mcid === mcid);
|
|
899
|
+
const elementNum = mark === void 0 ? void 0 : structElementNumById.get(mark.structureId);
|
|
900
|
+
return elementNum === void 0 ? pdfNull() : pdfRef(elementNum, 0);
|
|
901
|
+
});
|
|
904
902
|
nums.push(pdfNum(pageIndex), pdfArray(byMcid));
|
|
905
903
|
}
|
|
906
904
|
objects.push({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pdf-parser.js",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.17",
|
|
4
4
|
"description": "Hand-written, dependency-minimal PDF codec: parses arbitrary real-world PDFs and generates new ones, built on its own codec-owned LayoutDocument item model and Zod 4 codecs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|