pdf-parser.js 3.0.7 → 4.5.1

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