pdf-codec 3.1.4 → 3.3.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 (92) hide show
  1. package/README.md +4 -2
  2. package/dist/annotations.cjs +104 -0
  3. package/dist/annotations.d.cts +9 -0
  4. package/dist/annotations.d.ts +9 -0
  5. package/dist/annotations.js +103 -0
  6. package/dist/attachments.cjs +65 -0
  7. package/dist/attachments.d.cts +8 -0
  8. package/dist/attachments.d.ts +8 -0
  9. package/dist/attachments.js +64 -0
  10. package/dist/bytes/flate.cjs +1 -1
  11. package/dist/bytes/flate.js +1 -1
  12. package/dist/codec.d.cts +109 -0
  13. package/dist/codec.d.ts +109 -0
  14. package/dist/content-read.cjs +1 -1
  15. package/dist/content-read.js +1 -1
  16. package/dist/content-write.cjs +2 -2
  17. package/dist/content-write.js +2 -2
  18. package/dist/document.cjs +12 -3
  19. package/dist/document.d.cts +2 -0
  20. package/dist/document.d.ts +2 -0
  21. package/dist/document.js +12 -3
  22. package/dist/embedded-font-write.cjs +1 -1
  23. package/dist/embedded-font-write.js +1 -1
  24. package/dist/encrypt.cjs +1 -1
  25. package/dist/encrypt.js +1 -1
  26. package/dist/filters.cjs +1 -1
  27. package/dist/filters.js +1 -1
  28. package/dist/font-read.cjs +1 -1
  29. package/dist/font-read.js +1 -1
  30. package/dist/font-registry.cjs +1 -1
  31. package/dist/font-registry.js +1 -1
  32. package/dist/form.cjs +138 -0
  33. package/dist/form.d.cts +9 -0
  34. package/dist/form.d.ts +9 -0
  35. package/dist/form.js +137 -0
  36. package/dist/image/png-decode.cjs +1 -1
  37. package/dist/image/png-decode.js +1 -1
  38. package/dist/image/png-encode.cjs +1 -1
  39. package/dist/image/png-encode.js +1 -1
  40. package/dist/index.cjs +12 -2
  41. package/dist/index.d.cts +3 -3
  42. package/dist/index.d.ts +3 -3
  43. package/dist/index.js +3 -3
  44. package/dist/interpret.cjs +70 -10
  45. package/dist/interpret.d.cts +9 -1
  46. package/dist/interpret.d.ts +9 -1
  47. package/dist/interpret.js +70 -10
  48. package/dist/layout.cjs +132 -2
  49. package/dist/layout.d.cts +335 -1
  50. package/dist/layout.d.ts +335 -1
  51. package/dist/layout.js +124 -4
  52. package/dist/math-content-write.cjs +1 -1
  53. package/dist/math-content-write.js +1 -1
  54. package/dist/math-font.cjs +1 -1
  55. package/dist/math-font.js +1 -1
  56. package/dist/names.cjs +41 -0
  57. package/dist/names.d.cts +11 -0
  58. package/dist/names.d.ts +11 -0
  59. package/dist/names.js +40 -0
  60. package/dist/navigation.cjs +210 -0
  61. package/dist/navigation.d.cts +18 -0
  62. package/dist/navigation.d.ts +18 -0
  63. package/dist/navigation.js +207 -0
  64. package/dist/optional-content.cjs +63 -0
  65. package/dist/optional-content.d.cts +12 -0
  66. package/dist/optional-content.d.ts +12 -0
  67. package/dist/optional-content.js +62 -0
  68. package/dist/parse.cjs +1 -1
  69. package/dist/parse.d.cts +1 -1
  70. package/dist/parse.d.ts +1 -1
  71. package/dist/parse.js +1 -1
  72. package/dist/pdf-text.cjs +21 -0
  73. package/dist/pdf-text.d.cts +5 -0
  74. package/dist/pdf-text.d.ts +5 -0
  75. package/dist/pdf-text.js +19 -0
  76. package/dist/read.cjs +272 -72
  77. package/dist/read.d.cts +2 -4
  78. package/dist/read.d.ts +2 -4
  79. package/dist/read.js +269 -67
  80. package/dist/serialize.cjs +5 -1
  81. package/dist/serialize.d.cts +3 -2
  82. package/dist/serialize.d.ts +3 -2
  83. package/dist/serialize.js +5 -2
  84. package/dist/write.cjs +51 -5
  85. package/dist/write.js +51 -5
  86. package/dist/xmp.cjs +46 -0
  87. package/dist/xmp.d.cts +14 -0
  88. package/dist/xmp.d.ts +14 -0
  89. package/dist/xmp.js +45 -0
  90. package/dist/xref.cjs +2 -2
  91. package/dist/xref.js +2 -2
  92. package/package.json +2 -2
package/dist/read.cjs CHANGED
@@ -1,18 +1,26 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("./notes-annotation-author.cjs");
3
+ const require_objects = require("./objects.cjs");
4
+ const require_pdf_text = require("./pdf-text.cjs");
5
+ const require_bytes_writer = require("./bytes/writer.cjs");
6
+ const require_serialize = require("./serialize.cjs");
7
+ const require_matrix = require("./matrix.cjs");
8
+ const require_annotations = require("./annotations.cjs");
9
+ const require_filters = require("./filters.cjs");
2
10
  const require_util_base64 = require("./util/base64.cjs");
11
+ const require_attachments = require("./attachments.cjs");
3
12
  const require_bytes_crc32 = require("./bytes/crc32.cjs");
4
- const require_bytes_writer = require("./bytes/writer.cjs");
13
+ const require_form = require("./form.cjs");
14
+ const require_xmp = require("./xmp.cjs");
15
+ const require_optional_content = require("./optional-content.cjs");
5
16
  require("./layout.cjs");
6
17
  const require_diagnostics = require("./diagnostics.cjs");
7
- const require_objects = require("./objects.cjs");
8
- const require_filters = require("./filters.cjs");
9
18
  const require_document = require("./document.cjs");
10
19
  const require_util_abort = require("./util/abort.cjs");
11
20
  const require_font_read = require("./font-read.cjs");
12
21
  const require_images_read = require("./images-read.cjs");
13
- const require_matrix = require("./matrix.cjs");
14
22
  const require_interpret = require("./interpret.cjs");
15
- require("./notes-annotation-author.cjs");
23
+ const require_navigation = require("./navigation.cjs");
16
24
  //#region src/read.ts
17
25
  const PDF_HEADER_BYTES = new TextEncoder().encode("%PDF-");
18
26
  const HEADER_SEARCH_WINDOW = 1024;
@@ -38,29 +46,42 @@ function readPdf(bytes, options) {
38
46
  });
39
47
  const images = {};
40
48
  const imageIdCache = /* @__PURE__ */ new Map();
41
- const pages = doc.pages().map((pageDict) => {
49
+ const pageDicts = doc.pages();
50
+ const destinationRegistry = require_navigation.createDestinationRegistry(doc.catalog, doc, (obj) => doc.pageIndex(obj), sink);
51
+ const outline = require_navigation.readOutline(doc.catalog, destinationRegistry, doc, sink);
52
+ const attachments = require_attachments.readAttachments(doc.catalog, pageDicts, doc, sink);
53
+ const optionalContent = require_optional_content.readOptionalContent(doc.catalog, doc, sink);
54
+ const form = require_form.readAcroForm(doc.catalog, doc, (obj) => doc.pageIndex(obj), sink);
55
+ const source = readDocumentResidue(doc, sink);
56
+ const pageBoxRows = [];
57
+ const pages = pageDicts.map((pageDict, index) => {
42
58
  require_util_abort.throwIfAborted(signal);
43
- return readPage(pageDict, doc, fontResolver, images, imageIdCache, sink);
59
+ return readPage(index, pageDict, doc, fontResolver, images, imageIdCache, destinationRegistry, optionalContent.layerNameOf, pageBoxRows, sink);
44
60
  });
61
+ if (pageBoxRows.length > 0) source["page-boxes"] = {
62
+ format: "pdf",
63
+ xml: require_serialize.serializeObjectToText(require_objects.pdfArray(pageBoxRows))
64
+ };
45
65
  return {
46
66
  formatVersion: 1,
47
- metadata: readMetadata(doc.trailer, doc),
67
+ metadata: readMetadata(doc.trailer, doc, doc.catalog, sink),
48
68
  pages,
49
- images
69
+ images,
70
+ ...destinationRegistry.entries.length > 0 ? { destinations: [...destinationRegistry.entries] } : {},
71
+ ...outline.length > 0 ? { outline } : {},
72
+ ...attachments.length > 0 ? { attachments } : {},
73
+ ...optionalContent.layers.length > 0 ? { layers: [...optionalContent.layers] } : {},
74
+ ...form.length > 0 ? { form } : {},
75
+ ...Object.keys(source).length > 0 ? { source } : {}
50
76
  };
51
77
  }
52
- function readMediaBox(page) {
53
- const arr = require_objects.asArray(require_objects.dictGet(page, "MediaBox"));
54
- if (arr === void 0) return {
55
- llx: 0,
56
- lly: 0,
57
- urx: DEFAULT_PAGE_WIDTH_PT,
58
- ury: DEFAULT_PAGE_HEIGHT_PT
59
- };
78
+ function readDeclaredPageBox(page, key) {
79
+ const arr = require_objects.asArray(require_objects.dictGet(page, key));
80
+ if (arr === void 0) return;
60
81
  const a = require_objects.asNumber(arr[0]) ?? 0;
61
82
  const b = require_objects.asNumber(arr[1]) ?? 0;
62
- const c = require_objects.asNumber(arr[2]) ?? DEFAULT_PAGE_WIDTH_PT;
63
- const d = require_objects.asNumber(arr[3]) ?? DEFAULT_PAGE_HEIGHT_PT;
83
+ const c = require_objects.asNumber(arr[2]) ?? 0;
84
+ const d = require_objects.asNumber(arr[3]) ?? 0;
64
85
  return {
65
86
  llx: Math.min(a, c),
66
87
  lly: Math.min(b, d),
@@ -68,6 +89,33 @@ function readMediaBox(page) {
68
89
  ury: Math.max(b, d)
69
90
  };
70
91
  }
92
+ function readMediaBox(page) {
93
+ return readDeclaredPageBox(page, "MediaBox") ?? {
94
+ llx: 0,
95
+ lly: 0,
96
+ urx: DEFAULT_PAGE_WIDTH_PT,
97
+ ury: DEFAULT_PAGE_HEIGHT_PT
98
+ };
99
+ }
100
+ function rotatedRectBounds(rect, matrix) {
101
+ const transformed = [
102
+ [rect.llx, rect.lly],
103
+ [rect.urx, rect.lly],
104
+ [rect.llx, rect.ury],
105
+ [rect.urx, rect.ury]
106
+ ].map(([x, y]) => require_matrix.applyMatrix(matrix, {
107
+ x,
108
+ y
109
+ }));
110
+ const xs = transformed.map((point) => point.x);
111
+ const ys = transformed.map((point) => point.y);
112
+ return {
113
+ minX: Math.min(...xs),
114
+ minY: Math.min(...ys),
115
+ maxX: Math.max(...xs),
116
+ maxY: Math.max(...ys)
117
+ };
118
+ }
71
119
  function normalizeRotation(rotate) {
72
120
  if (rotate === void 0) return 0;
73
121
  const normalized = (Math.round(rotate / 90) * 90 % 360 + 360) % 360;
@@ -136,35 +184,141 @@ function readPageContentBytes(page, resolver, sink) {
136
184
  }
137
185
  return /* @__PURE__ */ new Uint8Array(0);
138
186
  }
139
- function readPage(page, resolver, fontResolver, images, imageIdCache, sink) {
187
+ function contentItemBounds(item) {
188
+ if (item.kind === "link" || item.kind === "internalLink") return;
189
+ const frameBounds = (xPt, yPt, widthPt, heightPt) => ({
190
+ minX: xPt,
191
+ minY: yPt,
192
+ maxX: xPt + widthPt,
193
+ maxY: yPt + heightPt
194
+ });
195
+ if (item.kind === "text" || item.kind === "image" || item.kind === "rect" || item.kind === "ellipse") {
196
+ if (item.kind !== "text" || item.rotationDeg === void 0 || item.rotationDeg % 180 === 0) return frameBounds(item.xPt, item.yPt, item.widthPt ?? 0, item.kind === "text" ? item.sizePt : item.heightPt);
197
+ const rotationDeg = item.rotationDeg;
198
+ const anchorX = item.xPt;
199
+ const anchorY = item.yPt;
200
+ const rotated = [
201
+ [0, 0],
202
+ [item.widthPt ?? 0, 0],
203
+ [0, item.sizePt],
204
+ [item.widthPt ?? 0, item.sizePt]
205
+ ].map(([dx, dy]) => require_matrix.rotatePointAboutCenter({
206
+ x: anchorX + dx,
207
+ y: anchorY + dy
208
+ }, {
209
+ x: anchorX,
210
+ y: anchorY
211
+ }, rotationDeg));
212
+ const xs = rotated.map((point) => point.x);
213
+ const ys = rotated.map((point) => point.y);
214
+ return {
215
+ minX: Math.min(...xs),
216
+ minY: Math.min(...ys),
217
+ maxX: Math.max(...xs),
218
+ maxY: Math.max(...ys)
219
+ };
220
+ }
221
+ if (item.kind === "line") return {
222
+ minX: Math.min(item.x1Pt, item.x2Pt),
223
+ minY: Math.min(item.y1Pt, item.y2Pt),
224
+ maxX: Math.max(item.x1Pt, item.x2Pt),
225
+ maxY: Math.max(item.y1Pt, item.y2Pt)
226
+ };
227
+ let minX = Number.POSITIVE_INFINITY;
228
+ let minY = Number.POSITIVE_INFINITY;
229
+ let maxX = Number.NEGATIVE_INFINITY;
230
+ let maxY = Number.NEGATIVE_INFINITY;
231
+ const include = (x, y) => {
232
+ minX = Math.min(minX, x);
233
+ minY = Math.min(minY, y);
234
+ maxX = Math.max(maxX, x);
235
+ maxY = Math.max(maxY, y);
236
+ };
237
+ for (const subpath of item.subpaths) {
238
+ include(subpath.startXPt, subpath.startYPt);
239
+ for (const segment of subpath.segments) {
240
+ include(segment.xPt, segment.yPt);
241
+ if (segment.kind === "cubic") {
242
+ include(segment.c1xPt, segment.c1yPt);
243
+ include(segment.c2xPt, segment.c2yPt);
244
+ }
245
+ }
246
+ }
247
+ return {
248
+ minX,
249
+ minY,
250
+ maxX,
251
+ maxY
252
+ };
253
+ }
254
+ function itemIntersectsVisibleRegion(item, widthPt, heightPt) {
255
+ if (item.kind === "link" || item.kind === "internalLink") return true;
256
+ const bounds = contentItemBounds(item);
257
+ if (bounds === void 0) return true;
258
+ return bounds.maxX >= 0 && bounds.minX <= widthPt && bounds.maxY >= 0 && bounds.minY <= heightPt;
259
+ }
260
+ function pageBoxResidueEntry(pageIndex, page, mediaBox, cropBox) {
261
+ const declaredBoxes = [
262
+ ["MediaBox", require_objects.dictGet(page, "MediaBox")],
263
+ ["CropBox", require_objects.dictGet(page, "CropBox")],
264
+ ["BleedBox", require_objects.dictGet(page, "BleedBox")],
265
+ ["TrimBox", require_objects.dictGet(page, "TrimBox")],
266
+ ["ArtBox", require_objects.dictGet(page, "ArtBox")]
267
+ ];
268
+ const cropDeclared = require_objects.dictGet(page, "CropBox") !== void 0;
269
+ const productionBoxDeclared = declaredBoxes.slice(2).some(([, value]) => value !== void 0);
270
+ if (!(cropDeclared && (cropBox.llx !== mediaBox.llx || cropBox.lly !== mediaBox.lly || cropBox.urx !== mediaBox.urx || cropBox.ury !== mediaBox.ury)) && !productionBoxDeclared) return;
271
+ const entries = { Page: require_objects.pdfNum(pageIndex) };
272
+ for (const [key, value] of declaredBoxes) if (value !== void 0) entries[key] = value;
273
+ return require_objects.pdfDict(entries);
274
+ }
275
+ function readPage(pageIndex, page, resolver, fontResolver, images, imageIdCache, destinationRegistry, layerNameOf, pageBoxRows, sink) {
140
276
  const resources = resolver.resolveDict(require_objects.dictGet(page, "Resources"));
141
277
  const mediaBox = readMediaBox(page);
278
+ let cropBox = readDeclaredPageBox(page, "CropBox") ?? mediaBox;
279
+ if (cropBox.urx - cropBox.llx <= 0 || cropBox.ury - cropBox.lly <= 0) {
280
+ sink({
281
+ code: "pdf/invalid-crop-box",
282
+ severity: "warning",
283
+ pageIndex,
284
+ message: "page /CropBox is degenerate (zero width or height); falling back to the /MediaBox as the visible region"
285
+ });
286
+ cropBox = mediaBox;
287
+ }
142
288
  const rotationResult = pageRotationTransform(normalizeRotation(require_objects.asNumber(require_objects.dictGet(page, "Rotate"))), mediaBox.urx - mediaBox.llx, mediaBox.ury - mediaBox.lly);
143
- const pageMatrix = require_matrix.multiplyMatrices(require_matrix.translationMatrix(-mediaBox.llx, -mediaBox.lly), rotationResult.matrix);
289
+ const visibleRect = rotatedRectBounds(cropBox, rotationResult.matrix);
290
+ const widthPt = visibleRect.maxX - visibleRect.minX;
291
+ const heightPt = visibleRect.maxY - visibleRect.minY;
292
+ const pageMatrix = require_matrix.multiplyMatrices(rotationResult.matrix, require_matrix.translationMatrix(-visibleRect.minX, -visibleRect.minY));
293
+ const boxRow = pageBoxResidueEntry(pageIndex, page, mediaBox, cropBox);
294
+ if (boxRow !== void 0) pageBoxRows.push(boxRow);
144
295
  const items = [];
145
296
  if (resources !== void 0) {
146
297
  const contentBytes = readPageContentBytes(page, resolver, sink);
147
298
  const extracted = require_interpret.interpretContentStream(contentBytes, resources, {
148
299
  fontMetrics: fontResolver.metrics,
149
300
  resolver,
150
- sink
301
+ sink,
302
+ layerNameOf
151
303
  });
152
304
  for (const item of extracted) {
153
305
  const converted = convertExtractedItem(item, pageMatrix, fontResolver, images, imageIdCache, resolver, sink);
154
- if (converted !== void 0) items.push(converted);
306
+ if (converted !== void 0 && itemIntersectsVisibleRegion(converted, widthPt, heightPt)) items.push(converted);
155
307
  }
156
308
  } else sink({
157
309
  code: "pdf/object-missing-value",
158
310
  severity: "warning",
159
311
  message: "page has no /Resources dict; its content stream cannot be interpreted"
160
312
  });
161
- items.push(...readLinkAnnotations(page, pageMatrix, resolver));
313
+ items.push(...readLinkAnnotations(page, pageMatrix, resolver, destinationRegistry));
162
314
  const notes = readPageNotes(page, resolver);
315
+ const annotations = require_annotations.readPageAnnotations(page, pageMatrix, resolver, sink);
163
316
  return {
164
- widthPt: rotationResult.widthPt,
165
- heightPt: rotationResult.heightPt,
317
+ widthPt,
318
+ heightPt,
166
319
  items,
167
- ...notes !== void 0 ? { notes } : {}
320
+ ...notes !== void 0 ? { notes } : {},
321
+ ...annotations.length > 0 ? { annotations } : {}
168
322
  };
169
323
  }
170
324
  function convertExtractedItem(item, pageMatrix, fontResolver, images, imageIdCache, resolver, sink) {
@@ -199,7 +353,10 @@ function convertText(item, pageMatrix, fontResolver) {
199
353
  sizePt: sizePt > 0 ? sizePt : item.sizePt,
200
354
  color: item.color,
201
355
  widthPt,
202
- rotationDeg: rotationDeg !== 0 ? rotationDeg : void 0
356
+ rotationDeg: rotationDeg !== 0 ? rotationDeg : void 0,
357
+ ...item.layerName !== void 0 ? { layer: item.layerName } : {},
358
+ ...item.actualText !== void 0 ? { actualText: item.actualText } : {},
359
+ ...item.alt !== void 0 ? { alt: item.alt } : {}
203
360
  };
204
361
  }
205
362
  function paintFields(paint) {
@@ -228,14 +385,16 @@ function convertRect(item, pageMatrix) {
228
385
  return {
229
386
  kind: "rect",
230
387
  ...transformBox(item, pageMatrix),
231
- ...paintFields(item)
388
+ ...paintFields(item),
389
+ ...item.layerName !== void 0 ? { layer: item.layerName } : {}
232
390
  };
233
391
  }
234
392
  function convertEllipse(item, pageMatrix) {
235
393
  return {
236
394
  kind: "ellipse",
237
395
  ...transformBox(item, pageMatrix),
238
- ...paintFields(item)
396
+ ...paintFields(item),
397
+ ...item.layerName !== void 0 ? { layer: item.layerName } : {}
239
398
  };
240
399
  }
241
400
  function convertLine(item, pageMatrix) {
@@ -254,7 +413,8 @@ function convertLine(item, pageMatrix) {
254
413
  x2Pt: p2.x,
255
414
  y2Pt: p2.y,
256
415
  color: item.color,
257
- widthPt: item.widthPt
416
+ widthPt: item.widthPt,
417
+ ...item.layerName !== void 0 ? { layer: item.layerName } : {}
258
418
  };
259
419
  }
260
420
  function transformSubpath(subpath, pageMatrix) {
@@ -309,7 +469,8 @@ function convertPath(item, pageMatrix) {
309
469
  subpaths: item.subpaths.map((subpath) => transformSubpath(subpath, pageMatrix)),
310
470
  ...item.fill !== void 0 ? { fill: item.fill } : {},
311
471
  ...item.fill !== void 0 && item.fillRule === "evenodd" ? { fillRule: "evenodd" } : {},
312
- ...item.stroke !== void 0 ? { stroke: item.stroke } : {}
472
+ ...item.stroke !== void 0 ? { stroke: item.stroke } : {},
473
+ ...item.layerName !== void 0 ? { layer: item.layerName } : {}
313
474
  };
314
475
  }
315
476
  function imagePlacementFrom(matrix) {
@@ -352,7 +513,8 @@ function convertImage(item, pageMatrix, images, cache, resolver, sink) {
352
513
  return {
353
514
  kind: "image",
354
515
  imageId,
355
- ...imagePlacementFrom(require_matrix.multiplyMatrices(item.matrix, pageMatrix))
516
+ ...imagePlacementFrom(require_matrix.multiplyMatrices(item.matrix, pageMatrix)),
517
+ ...item.layerName !== void 0 ? { layer: item.layerName } : {}
356
518
  };
357
519
  }
358
520
  function convertInlineImage(item, pageMatrix, images, resolver, sink) {
@@ -361,19 +523,22 @@ function convertInlineImage(item, pageMatrix, images, resolver, sink) {
361
523
  return {
362
524
  kind: "image",
363
525
  imageId: registerExtractedImage(decoded.format, decoded.bytes, decoded.widthPx, decoded.heightPx, images),
364
- ...imagePlacementFrom(require_matrix.multiplyMatrices(item.matrix, pageMatrix))
526
+ ...imagePlacementFrom(require_matrix.multiplyMatrices(item.matrix, pageMatrix)),
527
+ ...item.layerName !== void 0 ? { layer: item.layerName } : {}
365
528
  };
366
529
  }
367
- function readLinkAnnotations(page, pageMatrix, resolver) {
530
+ function readLinkAnnotations(page, pageMatrix, resolver, destinationRegistry) {
368
531
  const annotsArr = require_objects.asArray(require_objects.dictGet(page, "Annots"));
369
532
  if (annotsArr === void 0) return [];
370
533
  const links = [];
371
534
  for (const annotRef of annotsArr) {
372
535
  const annot = resolver.resolveDict(annotRef);
373
536
  if (annot === void 0 || require_objects.asName(require_objects.dictGet(annot, "Subtype")) !== "Link") continue;
374
- const uri = readLinkUri(annot, resolver);
375
537
  const rectArr = require_objects.asArray(require_objects.dictGet(annot, "Rect"));
376
- if (uri === void 0 || rectArr === void 0) continue;
538
+ if (rectArr === void 0) continue;
539
+ const uri = readLinkUri(annot, resolver);
540
+ const destination = uri === void 0 ? readInternalDestination(annot, resolver, destinationRegistry) : void 0;
541
+ if (uri === void 0 && destination === void 0) continue;
377
542
  const x1 = require_objects.asNumber(rectArr[0]) ?? 0;
378
543
  const y1 = require_objects.asNumber(rectArr[1]) ?? 0;
379
544
  const x2 = require_objects.asNumber(rectArr[2]) ?? 0;
@@ -386,13 +551,24 @@ function readLinkAnnotations(page, pageMatrix, resolver) {
386
551
  x: Math.max(x1, x2),
387
552
  y: Math.max(y1, y2)
388
553
  });
389
- links.push({
390
- kind: "link",
391
- uri,
554
+ const contentsObj = require_objects.dictGet(annot, "Contents");
555
+ const title = contentsObj?.kind === "string" ? require_pdf_text.decodePdfString(contentsObj.bytes) : void 0;
556
+ const box = {
392
557
  xPt: Math.min(p1.x, p2.x),
393
558
  yPt: Math.min(p1.y, p2.y),
394
559
  widthPt: Math.abs(p2.x - p1.x),
395
- heightPt: Math.abs(p2.y - p1.y)
560
+ heightPt: Math.abs(p2.y - p1.y),
561
+ ...title !== void 0 ? { title } : {}
562
+ };
563
+ if (uri !== void 0) links.push({
564
+ kind: "link",
565
+ uri,
566
+ ...box
567
+ });
568
+ else if (destination !== void 0) links.push({
569
+ kind: "internalLink",
570
+ destination,
571
+ ...box
396
572
  });
397
573
  }
398
574
  return links;
@@ -401,7 +577,13 @@ function readLinkUri(annot, resolver) {
401
577
  const action = resolver.resolveDict(require_objects.dictGet(annot, "A"));
402
578
  if (action === void 0 || require_objects.asName(require_objects.dictGet(action, "S")) !== "URI") return;
403
579
  const uriObj = require_objects.dictGet(action, "URI");
404
- return uriObj?.kind === "string" ? decodePdfString(uriObj.bytes) : void 0;
580
+ return uriObj?.kind === "string" ? require_pdf_text.decodePdfString(uriObj.bytes) : void 0;
581
+ }
582
+ function readInternalDestination(annot, resolver, destinationRegistry) {
583
+ const dest = require_objects.dictGet(annot, "Dest");
584
+ if (dest !== void 0) return destinationRegistry.intern(dest);
585
+ const action = resolver.resolveDict(require_objects.dictGet(annot, "A"));
586
+ if (action !== void 0 && require_objects.asName(require_objects.dictGet(action, "S")) === "GoTo") return destinationRegistry.intern(require_objects.dictGet(action, "D"));
405
587
  }
406
588
  function readPageNotes(page, resolver) {
407
589
  const annotsArr = require_objects.asArray(require_objects.dictGet(page, "Annots"));
@@ -410,49 +592,67 @@ function readPageNotes(page, resolver) {
410
592
  const annot = resolver.resolveDict(annotRef);
411
593
  if (annot === void 0 || require_objects.asName(require_objects.dictGet(annot, "Subtype")) !== "Text") continue;
412
594
  const titleObj = require_objects.dictGet(annot, "T");
413
- if ((titleObj?.kind === "string" ? decodePdfString(titleObj.bytes) : void 0) !== "documents.js:notes") continue;
595
+ if ((titleObj?.kind === "string" ? require_pdf_text.decodePdfString(titleObj.bytes) : void 0) !== "documents.js:notes") continue;
414
596
  const contentsObj = require_objects.dictGet(annot, "Contents");
415
- if (contentsObj?.kind === "string") return decodePdfString(contentsObj.bytes);
597
+ if (contentsObj?.kind === "string") return require_pdf_text.decodePdfString(contentsObj.bytes);
416
598
  }
417
599
  }
418
- function decodePdfString(bytes) {
419
- if (bytes.length >= 2 && bytes[0] === 254 && bytes[1] === 255) {
420
- let out = "";
421
- for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode((bytes[i] ?? 0) << 8 | (bytes[i + 1] ?? 0));
422
- return out;
423
- }
424
- return Array.from(bytes, (b) => String.fromCharCode(b)).join("");
425
- }
426
- const PDF_DATE_PATTERN = /^D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?([+\-Z])?(\d{2})?'?(\d{2})?'?$/;
427
- function parsePdfDate(raw) {
428
- if (raw === void 0) return;
429
- const match = PDF_DATE_PATTERN.exec(raw);
430
- if (match === null) return;
431
- const [, year, month = "01", day = "01", hour = "00", minute = "00", second = "00", tzSign, tzHour = "00", tzMinute = "00"] = match;
432
- return `${year}-${month}-${day}T${hour}:${minute}:${second}${tzSign === void 0 || tzSign === "Z" ? "Z" : `${tzSign}${tzHour}:${tzMinute}`}`;
433
- }
434
- function readMetadata(trailer, resolver) {
600
+ function readMetadata(trailer, resolver, catalog, sink) {
435
601
  const info = resolver.resolveDict(require_objects.dictGet(trailer, "Info"));
436
602
  if (info === void 0) return {};
437
603
  const stringField = (key) => {
438
604
  const obj = require_objects.dictGet(info, key);
439
- return obj?.kind === "string" ? decodePdfString(obj.bytes) : void 0;
605
+ return obj?.kind === "string" ? require_pdf_text.decodePdfString(obj.bytes) : void 0;
440
606
  };
441
607
  const keywords = stringField("Keywords")?.split(",").map((k) => k.trim()).filter((k) => k.length > 0);
608
+ const langObj = require_objects.dictGet(catalog, "Lang");
609
+ const xmp = xmpPacket(catalog, resolver, sink);
610
+ const mirrored = require_xmp.readXmpMetadata(xmp ?? "");
442
611
  return {
443
- title: stringField("Title"),
444
- author: stringField("Author"),
445
- subject: stringField("Subject"),
446
- keywords: keywords !== void 0 && keywords.length > 0 ? keywords : void 0,
447
- creator: stringField("Creator"),
448
- producer: stringField("Producer"),
449
- createdIso: parsePdfDate(stringField("CreationDate")),
450
- modifiedIso: parsePdfDate(stringField("ModDate"))
612
+ title: stringField("Title") ?? mirrored.title,
613
+ author: stringField("Author") ?? mirrored.author,
614
+ subject: stringField("Subject") ?? mirrored.subject,
615
+ keywords: (keywords !== void 0 && keywords.length > 0 ? keywords : void 0) ?? mirrored.keywords,
616
+ creator: stringField("Creator") ?? mirrored.creator,
617
+ producer: stringField("Producer") ?? mirrored.producer,
618
+ createdIso: require_pdf_text.parsePdfDate(stringField("CreationDate")) ?? mirrored.createdIso,
619
+ modifiedIso: require_pdf_text.parsePdfDate(stringField("ModDate")) ?? mirrored.modifiedIso,
620
+ ...langObj?.kind === "string" ? { language: require_pdf_text.decodePdfString(langObj.bytes) } : {}
621
+ };
622
+ }
623
+ function xmpPacket(catalog, resolver, sink) {
624
+ const metadataObj = resolver.resolve(require_objects.dictGet(catalog, "Metadata"));
625
+ if (metadataObj?.kind !== "stream") return;
626
+ const decoded = require_filters.decodeStream(metadataObj.raw, metadataObj.dict, sink);
627
+ return new TextDecoder().decode(decoded.bytes);
628
+ }
629
+ function readDocumentResidue(doc, sink) {
630
+ const source = {};
631
+ const residue = (key, obj) => {
632
+ if (obj !== void 0) source[key] = {
633
+ format: "pdf",
634
+ xml: require_serialize.serializeObjectToText(obj)
635
+ };
636
+ };
637
+ const catalog = doc.catalog;
638
+ const packet = xmpPacket(catalog, doc, sink);
639
+ if (packet !== void 0) source.xmp = {
640
+ format: "pdf",
641
+ xml: packet
451
642
  };
643
+ residue("viewer-preferences", require_objects.dictGet(catalog, "ViewerPreferences"));
644
+ residue("page-mode", require_objects.dictGet(catalog, "PageMode"));
645
+ residue("page-layout", require_objects.dictGet(catalog, "PageLayout"));
646
+ residue("open-action", require_objects.dictGet(catalog, "OpenAction"));
647
+ const outputIntents = require_objects.asArray(require_objects.dictGet(catalog, "OutputIntents"));
648
+ if (outputIntents !== void 0) residue("output-intents", require_objects.pdfArray(outputIntents.map((intent) => doc.resolve(intent) ?? require_objects.pdfNull())));
649
+ residue("piece-info", require_objects.dictGet(catalog, "PieceInfo"));
650
+ residue("legal", require_objects.dictGet(catalog, "Legal"));
651
+ residue("collection", require_objects.dictGet(catalog, "Collection"));
652
+ residue("trailer-id", require_objects.dictGet(doc.trailer, "ID"));
653
+ return source;
452
654
  }
453
655
  //#endregion
454
- exports.decodePdfString = decodePdfString;
455
656
  exports.normalizeRotation = normalizeRotation;
456
657
  exports.pageRotationTransform = pageRotationTransform;
457
- exports.parsePdfDate = parsePdfDate;
458
658
  exports.readPdf = readPdf;
package/dist/read.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { PdfDiagnosticSink } from "./diagnostics.cjs";
2
- import { LayoutDocument } from "./layout.cjs";
3
2
  import { r as Matrix } from "./matrix-B7_SBKQ5.cjs";
3
+ import { LayoutDocument } from "./layout.cjs";
4
4
  //#region src/read.d.ts
5
5
  interface ReadPdfOptions {
6
6
  readonly sink?: PdfDiagnosticSink;
@@ -15,7 +15,5 @@ interface PageRotationResult {
15
15
  readonly heightPt: number;
16
16
  }
17
17
  declare function pageRotationTransform(rotation: PageRotation, w: number, h: number): PageRotationResult;
18
- declare function decodePdfString(bytes: Uint8Array<ArrayBuffer>): string;
19
- declare function parsePdfDate(raw: string | undefined): string | undefined;
20
18
  //#endregion
21
- export { ReadPdfOptions, decodePdfString, normalizeRotation, pageRotationTransform, parsePdfDate, readPdf };
19
+ export { ReadPdfOptions, normalizeRotation, pageRotationTransform, readPdf };
package/dist/read.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { PdfDiagnosticSink } from "./diagnostics.js";
2
- import { LayoutDocument } from "./layout.js";
3
2
  import { r as Matrix } from "./matrix-B7_SBKQ5.js";
3
+ import { LayoutDocument } from "./layout.js";
4
4
  //#region src/read.d.ts
5
5
  interface ReadPdfOptions {
6
6
  readonly sink?: PdfDiagnosticSink;
@@ -15,7 +15,5 @@ interface PageRotationResult {
15
15
  readonly heightPt: number;
16
16
  }
17
17
  declare function pageRotationTransform(rotation: PageRotation, w: number, h: number): PageRotationResult;
18
- declare function decodePdfString(bytes: Uint8Array<ArrayBuffer>): string;
19
- declare function parsePdfDate(raw: string | undefined): string | undefined;
20
18
  //#endregion
21
- export { ReadPdfOptions, decodePdfString, normalizeRotation, pageRotationTransform, parsePdfDate, readPdf };
19
+ export { ReadPdfOptions, normalizeRotation, pageRotationTransform, readPdf };