pdf-codec 3.1.3 → 3.2.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 +2 -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 +128 -58
  77. package/dist/read.d.cts +2 -4
  78. package/dist/read.d.ts +2 -4
  79. package/dist/read.js +125 -53
  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/layout.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { ColorSchema, ContentStrokeStyleSchema, LayoutFontSchema, LayoutMetadataSchema } from "document-schema.js";
2
+ import { ColorSchema, ContentStrokeStyleSchema, LayoutFontSchema, LayoutMetadataSchema, SourceResidueSchema } from "document-schema.js";
3
3
  //#region src/layout.ts
4
4
  const LAYOUT_FORMAT_VERSION = 1;
5
5
  const LayoutTextSchema = z.object({
@@ -13,6 +13,9 @@ const LayoutTextSchema = z.object({
13
13
  widthPt: z.number().nonnegative().optional(),
14
14
  rotationDeg: z.number().optional(),
15
15
  underline: z.boolean().optional(),
16
+ layer: z.string().optional(),
17
+ actualText: z.string().optional(),
18
+ alt: z.string().optional(),
16
19
  sourcePath: z.string().optional()
17
20
  });
18
21
  const LayoutImageSchema = z.object({
@@ -23,6 +26,7 @@ const LayoutImageSchema = z.object({
23
26
  widthPt: z.number().positive(),
24
27
  heightPt: z.number().positive(),
25
28
  rotationDeg: z.number().optional(),
29
+ layer: z.string().optional(),
26
30
  sourcePath: z.string().optional()
27
31
  });
28
32
  const LayoutRectSchema = z.object({
@@ -36,6 +40,7 @@ const LayoutRectSchema = z.object({
36
40
  color: ColorSchema,
37
41
  widthPt: z.number().positive()
38
42
  }).optional(),
43
+ layer: z.string().optional(),
39
44
  sourcePath: z.string().optional()
40
45
  });
41
46
  const LayoutLineSchema = z.object({
@@ -47,6 +52,7 @@ const LayoutLineSchema = z.object({
47
52
  color: ColorSchema,
48
53
  widthPt: z.number().positive(),
49
54
  style: ContentStrokeStyleSchema.optional(),
55
+ layer: z.string().optional(),
50
56
  sourcePath: z.string().optional()
51
57
  });
52
58
  const LayoutEllipseSchema = z.object({
@@ -60,6 +66,7 @@ const LayoutEllipseSchema = z.object({
60
66
  color: ColorSchema,
61
67
  widthPt: z.number().positive()
62
68
  }).optional(),
69
+ layer: z.string().optional(),
63
70
  sourcePath: z.string().optional()
64
71
  });
65
72
  const LayoutPathSegmentSchema = z.discriminatedUnion("kind", [z.object({
@@ -91,6 +98,7 @@ const LayoutPathSchema = z.object({
91
98
  widthPt: z.number().positive()
92
99
  }).optional(),
93
100
  style: ContentStrokeStyleSchema.optional(),
101
+ layer: z.string().optional(),
94
102
  sourcePath: z.string().optional()
95
103
  });
96
104
  const LayoutLinkSchema = z.object({
@@ -100,8 +108,18 @@ const LayoutLinkSchema = z.object({
100
108
  yPt: z.number(),
101
109
  widthPt: z.number().nonnegative(),
102
110
  heightPt: z.number().nonnegative(),
111
+ title: z.string().optional(),
103
112
  sourcePath: z.string().optional()
104
113
  });
114
+ const LayoutInternalLinkSchema = z.object({
115
+ kind: z.literal("internalLink"),
116
+ destination: z.string(),
117
+ xPt: z.number(),
118
+ yPt: z.number(),
119
+ widthPt: z.number().nonnegative(),
120
+ heightPt: z.number().nonnegative(),
121
+ title: z.string().optional()
122
+ });
105
123
  const LayoutItemSchema = z.discriminatedUnion("kind", [
106
124
  LayoutTextSchema,
107
125
  LayoutImageSchema,
@@ -109,12 +127,44 @@ const LayoutItemSchema = z.discriminatedUnion("kind", [
109
127
  LayoutLineSchema,
110
128
  LayoutEllipseSchema,
111
129
  LayoutPathSchema,
112
- LayoutLinkSchema
130
+ LayoutLinkSchema,
131
+ LayoutInternalLinkSchema
113
132
  ]);
133
+ const LayoutAnnotationQuadSchema = z.tuple([
134
+ z.object({
135
+ xPt: z.number(),
136
+ yPt: z.number()
137
+ }),
138
+ z.object({
139
+ xPt: z.number(),
140
+ yPt: z.number()
141
+ }),
142
+ z.object({
143
+ xPt: z.number(),
144
+ yPt: z.number()
145
+ }),
146
+ z.object({
147
+ xPt: z.number(),
148
+ yPt: z.number()
149
+ })
150
+ ]);
151
+ const LayoutAnnotationSchema = z.object({
152
+ subtype: z.string(),
153
+ xPt: z.number(),
154
+ yPt: z.number(),
155
+ widthPt: z.number().nonnegative(),
156
+ heightPt: z.number().nonnegative(),
157
+ contents: z.string().optional(),
158
+ author: z.string().optional(),
159
+ modifiedIso: z.string().optional(),
160
+ quads: z.array(LayoutAnnotationQuadSchema).optional(),
161
+ source: SourceResidueSchema.optional()
162
+ });
114
163
  const LayoutPageSchema = z.object({
115
164
  widthPt: z.number().positive(),
116
165
  heightPt: z.number().positive(),
117
166
  items: z.array(LayoutItemSchema),
167
+ annotations: z.array(LayoutAnnotationSchema).optional(),
118
168
  notes: z.string().optional()
119
169
  });
120
170
  const LayoutImageAssetSchema = z.object({
@@ -123,11 +173,81 @@ const LayoutImageAssetSchema = z.object({
123
173
  widthPx: z.number().int().positive(),
124
174
  heightPx: z.number().int().positive()
125
175
  });
176
+ const LayoutDestinationTargetSchema = z.object({
177
+ kind: z.enum([
178
+ "xyz",
179
+ "fit",
180
+ "fitH",
181
+ "fitV",
182
+ "fitR",
183
+ "fitB",
184
+ "fitBH",
185
+ "fitBV"
186
+ ]),
187
+ leftPt: z.number().optional(),
188
+ topPt: z.number().optional(),
189
+ bottomPt: z.number().optional(),
190
+ rightPt: z.number().optional(),
191
+ zoom: z.number().optional()
192
+ });
193
+ const LayoutDestinationSchema = z.object({
194
+ name: z.string(),
195
+ pageIndex: z.number().int().nonnegative(),
196
+ target: LayoutDestinationTargetSchema
197
+ });
198
+ const LayoutOutlineItemSchema = z.lazy(() => z.object({
199
+ title: z.string(),
200
+ destination: z.string().optional(),
201
+ children: z.array(LayoutOutlineItemSchema)
202
+ }));
203
+ const LayoutAttachmentSchema = z.object({
204
+ name: z.string(),
205
+ description: z.string().optional(),
206
+ mimeType: z.string().optional(),
207
+ base64: z.string()
208
+ });
209
+ const LayoutFormWidgetSchema = z.object({
210
+ pageIndex: z.number().int().nonnegative(),
211
+ xPt: z.number(),
212
+ yPt: z.number(),
213
+ widthPt: z.number().nonnegative(),
214
+ heightPt: z.number().nonnegative()
215
+ });
216
+ const LayoutFormFieldSchema = z.lazy(() => z.object({
217
+ name: z.string(),
218
+ fieldType: z.enum([
219
+ "text",
220
+ "checkbox",
221
+ "radio",
222
+ "button",
223
+ "listbox",
224
+ "combobox",
225
+ "signature",
226
+ "group"
227
+ ]),
228
+ value: z.string().optional(),
229
+ checked: z.boolean().optional(),
230
+ options: z.array(z.string()).optional(),
231
+ alias: z.string().optional(),
232
+ readOnly: z.boolean().optional(),
233
+ widgets: z.array(LayoutFormWidgetSchema),
234
+ children: z.array(LayoutFormFieldSchema)
235
+ }));
236
+ const LayoutLayerSchema = z.object({
237
+ name: z.string(),
238
+ visible: z.boolean()
239
+ });
126
240
  const LayoutDocumentSchema = z.object({
127
241
  formatVersion: z.literal(1),
128
242
  metadata: LayoutMetadataSchema,
129
243
  pages: z.array(LayoutPageSchema),
130
- images: z.record(z.string(), LayoutImageAssetSchema)
244
+ images: z.record(z.string(), LayoutImageAssetSchema),
245
+ destinations: z.array(LayoutDestinationSchema).optional(),
246
+ outline: z.array(LayoutOutlineItemSchema).optional(),
247
+ attachments: z.array(LayoutAttachmentSchema).optional(),
248
+ layers: z.array(LayoutLayerSchema).optional(),
249
+ form: z.array(LayoutFormFieldSchema).optional(),
250
+ source: z.record(z.string(), SourceResidueSchema).optional()
131
251
  });
132
252
  //#endregion
133
- export { LAYOUT_FORMAT_VERSION, LayoutDocumentSchema, LayoutEllipseSchema, LayoutImageAssetSchema, LayoutImageSchema, LayoutItemSchema, LayoutLineSchema, LayoutLinkSchema, LayoutPageSchema, LayoutPathSchema, LayoutPathSegmentSchema, LayoutRectSchema, LayoutSubpathSchema, LayoutTextSchema };
253
+ export { LAYOUT_FORMAT_VERSION, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachmentSchema, LayoutDestinationSchema, LayoutDestinationTargetSchema, LayoutDocumentSchema, LayoutEllipseSchema, LayoutFormFieldSchema, LayoutFormWidgetSchema, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLinkSchema, LayoutItemSchema, LayoutLayerSchema, LayoutLineSchema, LayoutLinkSchema, LayoutOutlineItemSchema, LayoutPageSchema, LayoutPathSchema, LayoutPathSegmentSchema, LayoutRectSchema, LayoutSubpathSchema, LayoutTextSchema };
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_bytes_writer = require("./bytes/writer.cjs");
3
2
  const require_objects = require("./objects.cjs");
3
+ const require_bytes_writer = require("./bytes/writer.cjs");
4
4
  const require_serialize = require("./serialize.cjs");
5
5
  //#region src/math-content-write.ts
6
6
  function toPdfX(positioned, itemXPt) {
@@ -1,5 +1,5 @@
1
- import { ByteWriter } from "./bytes/writer.js";
2
1
  import { pdfDict, pdfHexString, pdfName } from "./objects.js";
2
+ import { ByteWriter } from "./bytes/writer.js";
3
3
  import { formatNumber, writeObject } from "./serialize.js";
4
4
  //#region src/math-content-write.ts
5
5
  function toPdfX(positioned, itemXPt) {
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_util_base64 = require("./util/base64.cjs");
2
3
  const require_sfnt = require("./sfnt.cjs");
3
4
  const require_cff_bounds = require("./cff-bounds.cjs");
4
5
  const require_cmap_table = require("./cmap-table.cjs");
5
- const require_util_base64 = require("./util/base64.cjs");
6
6
  const require_hmtx_table = require("./hmtx-table.cjs");
7
7
  const require_assets_stix_two_math_font = require("./assets/stix-two-math-font.cjs");
8
8
  const require_math_stretch = require("./math-stretch.cjs");
package/dist/math-font.js CHANGED
@@ -1,7 +1,7 @@
1
+ import { base64ToBytes } from "./util/base64.js";
1
2
  import { i16, parseSfnt, sfntTableBytes, u16 } from "./sfnt.js";
2
3
  import { parseCffGlyphBounds } from "./cff-bounds.js";
3
4
  import { buildCmapLookup } from "./cmap-table.js";
4
- import { base64ToBytes } from "./util/base64.js";
5
5
  import { parseHmtx } from "./hmtx-table.js";
6
6
  import { STIX_TWO_MATH_FONT_BASE64 } from "./assets/stix-two-math-font.js";
7
7
  import { assembleStretchyGlyph, scaleMathStretchConstruction } from "./math-stretch.js";
package/dist/names.cjs ADDED
@@ -0,0 +1,41 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_objects = require("./objects.cjs");
3
+ const require_pdf_text = require("./pdf-text.cjs");
4
+ //#region src/names.ts
5
+ function walkNameTree(root, resolver, sink) {
6
+ const entries = [];
7
+ collectNameTreeEntries(root, resolver, sink, entries, /* @__PURE__ */ new Set());
8
+ return entries;
9
+ }
10
+ function collectNameTreeEntries(node, resolver, sink, entries, visited) {
11
+ const dict = require_objects.asDict(resolver.resolve(node));
12
+ if (dict === void 0) {
13
+ if (node !== void 0) sink({
14
+ code: "pdf/name-tree-node-invalid",
15
+ severity: "warning",
16
+ message: "a name tree node did not resolve to a dictionary; skipping it"
17
+ });
18
+ return;
19
+ }
20
+ if (visited.has(dict)) {
21
+ sink({
22
+ code: "pdf/name-tree-cycle",
23
+ severity: "warning",
24
+ message: "the name tree contains a cycle; stopping descent at the repeated node"
25
+ });
26
+ return;
27
+ }
28
+ visited.add(dict);
29
+ const names = require_objects.asArray(require_objects.dictGet(dict, "Names"));
30
+ if (names !== void 0) for (let i = 0; i + 1 < names.length; i += 2) {
31
+ const key = names[i];
32
+ if (key?.kind === "string") entries.push({
33
+ name: require_pdf_text.decodePdfString(key.bytes),
34
+ value: names[i + 1]
35
+ });
36
+ }
37
+ const kids = require_objects.asArray(require_objects.dictGet(dict, "Kids"));
38
+ if (kids !== void 0) for (const kid of kids) collectNameTreeEntries(kid, resolver, sink, entries, visited);
39
+ }
40
+ //#endregion
41
+ exports.walkNameTree = walkNameTree;
@@ -0,0 +1,11 @@
1
+ import { PdfDiagnosticSink } from "./diagnostics.cjs";
2
+ import { PdfObject } from "./objects.cjs";
3
+ import { PdfObjectResolver } from "./interpret.cjs";
4
+ //#region src/names.d.ts
5
+ interface NameTreeEntry {
6
+ readonly name: string;
7
+ readonly value: PdfObject;
8
+ }
9
+ declare function walkNameTree(root: PdfObject | undefined, resolver: PdfObjectResolver, sink: PdfDiagnosticSink): NameTreeEntry[];
10
+ //#endregion
11
+ export { NameTreeEntry, walkNameTree };
@@ -0,0 +1,11 @@
1
+ import { PdfDiagnosticSink } from "./diagnostics.js";
2
+ import { PdfObject } from "./objects.js";
3
+ import { PdfObjectResolver } from "./interpret.js";
4
+ //#region src/names.d.ts
5
+ interface NameTreeEntry {
6
+ readonly name: string;
7
+ readonly value: PdfObject;
8
+ }
9
+ declare function walkNameTree(root: PdfObject | undefined, resolver: PdfObjectResolver, sink: PdfDiagnosticSink): NameTreeEntry[];
10
+ //#endregion
11
+ export { NameTreeEntry, walkNameTree };
package/dist/names.js ADDED
@@ -0,0 +1,40 @@
1
+ import { asArray, asDict, dictGet } from "./objects.js";
2
+ import { decodePdfString } from "./pdf-text.js";
3
+ //#region src/names.ts
4
+ function walkNameTree(root, resolver, sink) {
5
+ const entries = [];
6
+ collectNameTreeEntries(root, resolver, sink, entries, /* @__PURE__ */ new Set());
7
+ return entries;
8
+ }
9
+ function collectNameTreeEntries(node, resolver, sink, entries, visited) {
10
+ const dict = asDict(resolver.resolve(node));
11
+ if (dict === void 0) {
12
+ if (node !== void 0) sink({
13
+ code: "pdf/name-tree-node-invalid",
14
+ severity: "warning",
15
+ message: "a name tree node did not resolve to a dictionary; skipping it"
16
+ });
17
+ return;
18
+ }
19
+ if (visited.has(dict)) {
20
+ sink({
21
+ code: "pdf/name-tree-cycle",
22
+ severity: "warning",
23
+ message: "the name tree contains a cycle; stopping descent at the repeated node"
24
+ });
25
+ return;
26
+ }
27
+ visited.add(dict);
28
+ const names = asArray(dictGet(dict, "Names"));
29
+ if (names !== void 0) for (let i = 0; i + 1 < names.length; i += 2) {
30
+ const key = names[i];
31
+ if (key?.kind === "string") entries.push({
32
+ name: decodePdfString(key.bytes),
33
+ value: names[i + 1]
34
+ });
35
+ }
36
+ const kids = asArray(dictGet(dict, "Kids"));
37
+ if (kids !== void 0) for (const kid of kids) collectNameTreeEntries(kid, resolver, sink, entries, visited);
38
+ }
39
+ //#endregion
40
+ export { walkNameTree };
@@ -0,0 +1,210 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_objects = require("./objects.cjs");
3
+ const require_pdf_text = require("./pdf-text.cjs");
4
+ const require_names = require("./names.cjs");
5
+ //#region src/navigation.ts
6
+ function coordinateAt(arr, index) {
7
+ return require_objects.asNumber(arr[index]);
8
+ }
9
+ function parseDestination(value, resolver, pageIndex, sink) {
10
+ const arr = require_objects.asArray(resolver.resolve(value));
11
+ if (arr === void 0 || arr.length < 2) {
12
+ sink({
13
+ code: "pdf/destination-invalid",
14
+ severity: "warning",
15
+ message: "a destination is not a display destination array; skipping it"
16
+ });
17
+ return;
18
+ }
19
+ const pageEl = arr[0];
20
+ const resolvedPageIndex = pageEl?.kind === "number" ? Number.isInteger(pageEl.value) && pageEl.value >= 0 ? pageEl.value : void 0 : pageIndex(pageEl);
21
+ if (resolvedPageIndex === void 0) {
22
+ sink({
23
+ code: "pdf/destination-invalid",
24
+ severity: "warning",
25
+ message: "a destination names a page that is not in the document's page tree; skipping it"
26
+ });
27
+ return;
28
+ }
29
+ const type = require_objects.asName(arr[1]);
30
+ if (type === "XYZ") return {
31
+ pageIndex: resolvedPageIndex,
32
+ target: {
33
+ kind: "xyz",
34
+ ...optionalCoords(arr, [
35
+ ["leftPt", 2],
36
+ ["topPt", 3],
37
+ ["zoom", 4]
38
+ ])
39
+ }
40
+ };
41
+ if (type === "Fit") return {
42
+ pageIndex: resolvedPageIndex,
43
+ target: { kind: "fit" }
44
+ };
45
+ if (type === "FitH") return {
46
+ pageIndex: resolvedPageIndex,
47
+ target: {
48
+ kind: "fitH",
49
+ ...optionalCoords(arr, [["topPt", 2]])
50
+ }
51
+ };
52
+ if (type === "FitV") return {
53
+ pageIndex: resolvedPageIndex,
54
+ target: {
55
+ kind: "fitV",
56
+ ...optionalCoords(arr, [["leftPt", 2]])
57
+ }
58
+ };
59
+ if (type === "FitR") return {
60
+ pageIndex: resolvedPageIndex,
61
+ target: {
62
+ kind: "fitR",
63
+ ...optionalCoords(arr, [
64
+ ["leftPt", 2],
65
+ ["bottomPt", 3],
66
+ ["rightPt", 4],
67
+ ["topPt", 5]
68
+ ])
69
+ }
70
+ };
71
+ if (type === "FitB") return {
72
+ pageIndex: resolvedPageIndex,
73
+ target: { kind: "fitB" }
74
+ };
75
+ if (type === "FitBH") return {
76
+ pageIndex: resolvedPageIndex,
77
+ target: {
78
+ kind: "fitBH",
79
+ ...optionalCoords(arr, [["topPt", 2]])
80
+ }
81
+ };
82
+ if (type === "FitBV") return {
83
+ pageIndex: resolvedPageIndex,
84
+ target: {
85
+ kind: "fitBV",
86
+ ...optionalCoords(arr, [["leftPt", 2]])
87
+ }
88
+ };
89
+ sink({
90
+ code: "pdf/destination-invalid",
91
+ severity: "warning",
92
+ message: `a destination carries unknown display type /${type ?? "?"}; skipping it`
93
+ });
94
+ }
95
+ function optionalCoords(arr, fields) {
96
+ const out = {};
97
+ for (const [field, index] of fields) {
98
+ const value = coordinateAt(arr, index);
99
+ if (value !== void 0) out[field] = value;
100
+ }
101
+ return out;
102
+ }
103
+ function createDestinationRegistry(catalog, resolver, pageIndex, sink) {
104
+ const entries = [];
105
+ const byName = /* @__PURE__ */ new Map();
106
+ const add = (name, parsed) => {
107
+ const entry = {
108
+ name,
109
+ pageIndex: parsed.pageIndex,
110
+ target: parsed.target
111
+ };
112
+ entries.push(entry);
113
+ byName.set(name, entry);
114
+ };
115
+ const destsDict = resolver.resolveDict(require_objects.dictGet(catalog, "Dests"));
116
+ if (destsDict !== void 0) for (const [name, value] of destsDict.entries) {
117
+ if (byName.has(name)) {
118
+ sink({
119
+ code: "pdf/destination-duplicate",
120
+ severity: "warning",
121
+ message: `destination name "${name}" is declared more than once; keeping the first`
122
+ });
123
+ continue;
124
+ }
125
+ const parsed = parseDestination(value, resolver, pageIndex, sink);
126
+ if (parsed !== void 0) add(name, parsed);
127
+ }
128
+ const namesRoot = resolver.resolveDict(require_objects.dictGet(catalog, "Names"));
129
+ for (const entry of require_names.walkNameTree(namesRoot === void 0 ? void 0 : require_objects.dictGet(namesRoot, "Dests"), resolver, sink)) {
130
+ if (byName.has(entry.name)) {
131
+ sink({
132
+ code: "pdf/destination-duplicate",
133
+ severity: "warning",
134
+ message: `destination name "${entry.name}" is declared more than once; keeping the first`
135
+ });
136
+ continue;
137
+ }
138
+ const parsed = parseDestination(entry.value, resolver, pageIndex, sink);
139
+ if (parsed !== void 0) add(entry.name, parsed);
140
+ }
141
+ const minted = (obj) => {
142
+ const parsed = parseDestination(obj, resolver, pageIndex, sink);
143
+ if (parsed === void 0) return;
144
+ let n = 1;
145
+ while (byName.has(`dest${n}`)) n++;
146
+ const name = `dest${n}`;
147
+ add(name, parsed);
148
+ return name;
149
+ };
150
+ return {
151
+ entries,
152
+ intern(obj) {
153
+ const resolved = resolver.resolve(obj);
154
+ if (resolved?.kind === "string") {
155
+ const name = require_pdf_text.decodePdfString(resolved.bytes);
156
+ if (byName.has(name)) return name;
157
+ sink({
158
+ code: "pdf/destination-unresolved",
159
+ severity: "warning",
160
+ message: `a destination names "${name}", which no /Dests or /Names /Dests entry declares`
161
+ });
162
+ return;
163
+ }
164
+ if (resolved?.kind === "array") return minted(resolved);
165
+ }
166
+ };
167
+ }
168
+ function readOutline(catalog, registry, resolver, sink) {
169
+ const root = resolver.resolveDict(require_objects.dictGet(catalog, "Outlines"));
170
+ const first = root === void 0 ? void 0 : resolver.resolveDict(require_objects.dictGet(root, "First"));
171
+ if (first === void 0) return [];
172
+ const items = [];
173
+ walkOutlineSiblings(first, items, registry, resolver, sink, /* @__PURE__ */ new Set());
174
+ return items;
175
+ }
176
+ function walkOutlineSiblings(node, out, registry, resolver, sink, visited) {
177
+ let current = node;
178
+ while (current !== void 0) {
179
+ if (visited.has(current)) {
180
+ sink({
181
+ code: "pdf/outline-cycle",
182
+ severity: "warning",
183
+ message: "the outline contains a cycle; stopping the sibling chain at the repeated item"
184
+ });
185
+ return;
186
+ }
187
+ visited.add(current);
188
+ const titleObj = require_objects.dictGet(current, "Title");
189
+ const children = [];
190
+ const childFirst = resolver.resolveDict(require_objects.dictGet(current, "First"));
191
+ if (childFirst !== void 0) walkOutlineSiblings(childFirst, children, registry, resolver, sink, visited);
192
+ const destination = internOutlineDestination(current, registry, resolver);
193
+ out.push({
194
+ title: titleObj?.kind === "string" ? require_pdf_text.decodePdfString(titleObj.bytes) : "",
195
+ ...destination !== void 0 ? { destination } : {},
196
+ children
197
+ });
198
+ current = resolver.resolveDict(require_objects.dictGet(current, "Next"));
199
+ }
200
+ }
201
+ function internOutlineDestination(node, registry, resolver) {
202
+ const dest = require_objects.dictGet(node, "Dest");
203
+ if (dest !== void 0) return registry.intern(dest);
204
+ const action = resolver.resolveDict(require_objects.dictGet(node, "A"));
205
+ if (action !== void 0 && require_objects.asName(require_objects.dictGet(action, "S")) === "GoTo") return registry.intern(require_objects.dictGet(action, "D"));
206
+ }
207
+ //#endregion
208
+ exports.createDestinationRegistry = createDestinationRegistry;
209
+ exports.parseDestination = parseDestination;
210
+ exports.readOutline = readOutline;
@@ -0,0 +1,18 @@
1
+ import { PdfDiagnosticSink } from "./diagnostics.cjs";
2
+ import { PdfDict, PdfObject } from "./objects.cjs";
3
+ import { PdfObjectResolver } from "./interpret.cjs";
4
+ import { LayoutDestination, LayoutDestinationTarget, LayoutOutlineItem } from "./layout.cjs";
5
+ //#region src/navigation.d.ts
6
+ type PageIndexLookup = (obj: PdfObject | undefined) => number | undefined;
7
+ declare function parseDestination(value: PdfObject | undefined, resolver: PdfObjectResolver, pageIndex: PageIndexLookup, sink: PdfDiagnosticSink): {
8
+ pageIndex: number;
9
+ target: LayoutDestinationTarget;
10
+ } | undefined;
11
+ interface DestinationRegistry {
12
+ readonly entries: readonly LayoutDestination[];
13
+ intern(obj: PdfObject | undefined): string | undefined;
14
+ }
15
+ declare function createDestinationRegistry(catalog: PdfDict, resolver: PdfObjectResolver, pageIndex: PageIndexLookup, sink: PdfDiagnosticSink): DestinationRegistry;
16
+ declare function readOutline(catalog: PdfDict, registry: DestinationRegistry, resolver: PdfObjectResolver, sink: PdfDiagnosticSink): LayoutOutlineItem[];
17
+ //#endregion
18
+ export { DestinationRegistry, PageIndexLookup, createDestinationRegistry, parseDestination, readOutline };
@@ -0,0 +1,18 @@
1
+ import { PdfDiagnosticSink } from "./diagnostics.js";
2
+ import { PdfDict, PdfObject } from "./objects.js";
3
+ import { PdfObjectResolver } from "./interpret.js";
4
+ import { LayoutDestination, LayoutDestinationTarget, LayoutOutlineItem } from "./layout.js";
5
+ //#region src/navigation.d.ts
6
+ type PageIndexLookup = (obj: PdfObject | undefined) => number | undefined;
7
+ declare function parseDestination(value: PdfObject | undefined, resolver: PdfObjectResolver, pageIndex: PageIndexLookup, sink: PdfDiagnosticSink): {
8
+ pageIndex: number;
9
+ target: LayoutDestinationTarget;
10
+ } | undefined;
11
+ interface DestinationRegistry {
12
+ readonly entries: readonly LayoutDestination[];
13
+ intern(obj: PdfObject | undefined): string | undefined;
14
+ }
15
+ declare function createDestinationRegistry(catalog: PdfDict, resolver: PdfObjectResolver, pageIndex: PageIndexLookup, sink: PdfDiagnosticSink): DestinationRegistry;
16
+ declare function readOutline(catalog: PdfDict, registry: DestinationRegistry, resolver: PdfObjectResolver, sink: PdfDiagnosticSink): LayoutOutlineItem[];
17
+ //#endregion
18
+ export { DestinationRegistry, PageIndexLookup, createDestinationRegistry, parseDestination, readOutline };