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 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 if (nibble === REAL_NIBBLE_MINUS) text += "-";
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 if (nibble === REAL_NIBBLE_MINUS) text += "-";
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
- for (let i = 0; i < text.length; i++) {
44
- const code = text.charCodeAt(i);
45
- bytes[2 + i * 2] = code >> 8 & 255;
46
- bytes[2 + i * 2 + 1] = code & 255;
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
- for (let y = 0; y < raw.height; y++) for (let x = 0; x < raw.width; x++) {
149
- const sample = raw.data[y * raw.width + x] ?? 0;
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 index = y * rowBytes + (x >> 3);
153
- packed[index] = (packed[index] ?? 0) | 128 >> (x & 7);
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(asset.original.filter === "jbig2" ? "JBIG2Decode" : "JPXDecode")]
219
+ ["Filter", require_objects.pdfName(original.filter === "jbig2" ? "JBIG2Decode" : "JPXDecode")]
214
220
  ]);
215
- if (asset.original.filter === "jbig2") {
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)(asset.original.base64),
222
- ...png.alpha !== void 0 ? { alpha: png.alpha } : {}
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 use = embeddedUses.get(resolved.face) ?? {
356
- texts: [],
357
- codePoints: /* @__PURE__ */ new Set()
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, use]] of sortedEmbeddedUses.entries()) embeddedAllocs.set(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: use.texts,
411
- codePoints: use.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
- if (outlineRootNum !== void 0) {
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
- }
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 countElements = (elements) => {
460
- let n = 0;
459
+ const allocateStructureElements = (elements) => {
461
460
  for (const element of elements) {
462
461
  structElementNumById.set(element.id, nextObjNum++);
463
- n += 1 + countElements(element.children);
462
+ allocateStructureElements(element.children);
464
463
  }
465
- return n;
466
464
  };
467
- const structElementCount = countElements(doc.structure ?? []);
468
- const structRootNum = structElementCount > 0 ? nextObjNum++ : void 0;
469
- const structParentTreeNum = structElementCount > 0 ? nextObjNum++ : void 0;
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 && (doc.outline ?? []).length > 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.length > 0 && field.name.startsWith(`${parentName}.`) ? field.name.slice(parentName.length + 1) : field.name;
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.checked === false || field.value === void 0 ? field.value ?? (field.checked === true ? "Yes" : "Off") : field.value)]);
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.widgets.length > 1 && firstWidget !== void 0) {
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 && structParentTreeNum !== 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].sort((a, b) => a - b), [...usedGlyphs.keys()].sort((a, b) => a - b));
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 ((markedStructureByPage.get(pageIndex) ?? []).length > 0) pageEntries.set("StructParents", require_objects.pdfNum(pageIndex));
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 }, () => require_objects.pdfNull());
901
- for (const mark of marks) {
902
- const elementNum = structElementNumById.get(mark.structureId);
903
- if (elementNum !== void 0) byMcid[mark.mcid] = require_objects.pdfRef(elementNum, 0);
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
- for (let i = 0; i < text.length; i++) {
43
- const code = text.charCodeAt(i);
44
- bytes[2 + i * 2] = code >> 8 & 255;
45
- bytes[2 + i * 2 + 1] = code & 255;
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
- for (let y = 0; y < raw.height; y++) for (let x = 0; x < raw.width; x++) {
148
- const sample = raw.data[y * raw.width + x] ?? 0;
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 index = y * rowBytes + (x >> 3);
152
- packed[index] = (packed[index] ?? 0) | 128 >> (x & 7);
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(asset.original.filter === "jbig2" ? "JBIG2Decode" : "JPXDecode")]
218
+ ["Filter", pdfName(original.filter === "jbig2" ? "JBIG2Decode" : "JPXDecode")]
213
219
  ]);
214
- if (asset.original.filter === "jbig2") {
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(asset.original.base64),
221
- ...png.alpha !== void 0 ? { alpha: png.alpha } : {}
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 use = embeddedUses.get(resolved.face) ?? {
355
- texts: [],
356
- codePoints: /* @__PURE__ */ new Set()
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, use]] of sortedEmbeddedUses.entries()) embeddedAllocs.set(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: use.texts,
410
- codePoints: use.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
- if (outlineRootNum !== void 0) {
425
- const countItems = (items) => {
426
- let n = 0;
427
- for (const item of items) n += 1 + countItems(item.children);
428
- return n;
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 countElements = (elements) => {
459
- let n = 0;
458
+ const allocateStructureElements = (elements) => {
460
459
  for (const element of elements) {
461
460
  structElementNumById.set(element.id, nextObjNum++);
462
- n += 1 + countElements(element.children);
461
+ allocateStructureElements(element.children);
463
462
  }
464
- return n;
465
463
  };
466
- const structElementCount = countElements(doc.structure ?? []);
467
- const structRootNum = structElementCount > 0 ? nextObjNum++ : void 0;
468
- const structParentTreeNum = structElementCount > 0 ? nextObjNum++ : void 0;
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 && (doc.outline ?? []).length > 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.length > 0 && field.name.startsWith(`${parentName}.`) ? field.name.slice(parentName.length + 1) : field.name;
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.checked === false || field.value === void 0 ? field.value ?? (field.checked === true ? "Yes" : "Off") : field.value)]);
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.widgets.length > 1 && firstWidget !== void 0) {
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 && structParentTreeNum !== 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].sort((a, b) => a - b), [...usedGlyphs.keys()].sort((a, b) => a - b));
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 ((markedStructureByPage.get(pageIndex) ?? []).length > 0) pageEntries.set("StructParents", pdfNum(pageIndex));
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 }, () => pdfNull());
900
- for (const mark of marks) {
901
- const elementNum = structElementNumById.get(mark.structureId);
902
- if (elementNum !== void 0) byMcid[mark.mcid] = pdfRef(elementNum, 0);
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.15",
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": {