pdf-codec 3.1.4 → 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
@@ -0,0 +1,207 @@
1
+ import { asArray, asName, asNumber, dictGet } from "./objects.js";
2
+ import { decodePdfString } from "./pdf-text.js";
3
+ import { walkNameTree } from "./names.js";
4
+ //#region src/navigation.ts
5
+ function coordinateAt(arr, index) {
6
+ return asNumber(arr[index]);
7
+ }
8
+ function parseDestination(value, resolver, pageIndex, sink) {
9
+ const arr = asArray(resolver.resolve(value));
10
+ if (arr === void 0 || arr.length < 2) {
11
+ sink({
12
+ code: "pdf/destination-invalid",
13
+ severity: "warning",
14
+ message: "a destination is not a display destination array; skipping it"
15
+ });
16
+ return;
17
+ }
18
+ const pageEl = arr[0];
19
+ const resolvedPageIndex = pageEl?.kind === "number" ? Number.isInteger(pageEl.value) && pageEl.value >= 0 ? pageEl.value : void 0 : pageIndex(pageEl);
20
+ if (resolvedPageIndex === void 0) {
21
+ sink({
22
+ code: "pdf/destination-invalid",
23
+ severity: "warning",
24
+ message: "a destination names a page that is not in the document's page tree; skipping it"
25
+ });
26
+ return;
27
+ }
28
+ const type = asName(arr[1]);
29
+ if (type === "XYZ") return {
30
+ pageIndex: resolvedPageIndex,
31
+ target: {
32
+ kind: "xyz",
33
+ ...optionalCoords(arr, [
34
+ ["leftPt", 2],
35
+ ["topPt", 3],
36
+ ["zoom", 4]
37
+ ])
38
+ }
39
+ };
40
+ if (type === "Fit") return {
41
+ pageIndex: resolvedPageIndex,
42
+ target: { kind: "fit" }
43
+ };
44
+ if (type === "FitH") return {
45
+ pageIndex: resolvedPageIndex,
46
+ target: {
47
+ kind: "fitH",
48
+ ...optionalCoords(arr, [["topPt", 2]])
49
+ }
50
+ };
51
+ if (type === "FitV") return {
52
+ pageIndex: resolvedPageIndex,
53
+ target: {
54
+ kind: "fitV",
55
+ ...optionalCoords(arr, [["leftPt", 2]])
56
+ }
57
+ };
58
+ if (type === "FitR") return {
59
+ pageIndex: resolvedPageIndex,
60
+ target: {
61
+ kind: "fitR",
62
+ ...optionalCoords(arr, [
63
+ ["leftPt", 2],
64
+ ["bottomPt", 3],
65
+ ["rightPt", 4],
66
+ ["topPt", 5]
67
+ ])
68
+ }
69
+ };
70
+ if (type === "FitB") return {
71
+ pageIndex: resolvedPageIndex,
72
+ target: { kind: "fitB" }
73
+ };
74
+ if (type === "FitBH") return {
75
+ pageIndex: resolvedPageIndex,
76
+ target: {
77
+ kind: "fitBH",
78
+ ...optionalCoords(arr, [["topPt", 2]])
79
+ }
80
+ };
81
+ if (type === "FitBV") return {
82
+ pageIndex: resolvedPageIndex,
83
+ target: {
84
+ kind: "fitBV",
85
+ ...optionalCoords(arr, [["leftPt", 2]])
86
+ }
87
+ };
88
+ sink({
89
+ code: "pdf/destination-invalid",
90
+ severity: "warning",
91
+ message: `a destination carries unknown display type /${type ?? "?"}; skipping it`
92
+ });
93
+ }
94
+ function optionalCoords(arr, fields) {
95
+ const out = {};
96
+ for (const [field, index] of fields) {
97
+ const value = coordinateAt(arr, index);
98
+ if (value !== void 0) out[field] = value;
99
+ }
100
+ return out;
101
+ }
102
+ function createDestinationRegistry(catalog, resolver, pageIndex, sink) {
103
+ const entries = [];
104
+ const byName = /* @__PURE__ */ new Map();
105
+ const add = (name, parsed) => {
106
+ const entry = {
107
+ name,
108
+ pageIndex: parsed.pageIndex,
109
+ target: parsed.target
110
+ };
111
+ entries.push(entry);
112
+ byName.set(name, entry);
113
+ };
114
+ const destsDict = resolver.resolveDict(dictGet(catalog, "Dests"));
115
+ if (destsDict !== void 0) for (const [name, value] of destsDict.entries) {
116
+ if (byName.has(name)) {
117
+ sink({
118
+ code: "pdf/destination-duplicate",
119
+ severity: "warning",
120
+ message: `destination name "${name}" is declared more than once; keeping the first`
121
+ });
122
+ continue;
123
+ }
124
+ const parsed = parseDestination(value, resolver, pageIndex, sink);
125
+ if (parsed !== void 0) add(name, parsed);
126
+ }
127
+ const namesRoot = resolver.resolveDict(dictGet(catalog, "Names"));
128
+ for (const entry of walkNameTree(namesRoot === void 0 ? void 0 : dictGet(namesRoot, "Dests"), resolver, sink)) {
129
+ if (byName.has(entry.name)) {
130
+ sink({
131
+ code: "pdf/destination-duplicate",
132
+ severity: "warning",
133
+ message: `destination name "${entry.name}" is declared more than once; keeping the first`
134
+ });
135
+ continue;
136
+ }
137
+ const parsed = parseDestination(entry.value, resolver, pageIndex, sink);
138
+ if (parsed !== void 0) add(entry.name, parsed);
139
+ }
140
+ const minted = (obj) => {
141
+ const parsed = parseDestination(obj, resolver, pageIndex, sink);
142
+ if (parsed === void 0) return;
143
+ let n = 1;
144
+ while (byName.has(`dest${n}`)) n++;
145
+ const name = `dest${n}`;
146
+ add(name, parsed);
147
+ return name;
148
+ };
149
+ return {
150
+ entries,
151
+ intern(obj) {
152
+ const resolved = resolver.resolve(obj);
153
+ if (resolved?.kind === "string") {
154
+ const name = decodePdfString(resolved.bytes);
155
+ if (byName.has(name)) return name;
156
+ sink({
157
+ code: "pdf/destination-unresolved",
158
+ severity: "warning",
159
+ message: `a destination names "${name}", which no /Dests or /Names /Dests entry declares`
160
+ });
161
+ return;
162
+ }
163
+ if (resolved?.kind === "array") return minted(resolved);
164
+ }
165
+ };
166
+ }
167
+ function readOutline(catalog, registry, resolver, sink) {
168
+ const root = resolver.resolveDict(dictGet(catalog, "Outlines"));
169
+ const first = root === void 0 ? void 0 : resolver.resolveDict(dictGet(root, "First"));
170
+ if (first === void 0) return [];
171
+ const items = [];
172
+ walkOutlineSiblings(first, items, registry, resolver, sink, /* @__PURE__ */ new Set());
173
+ return items;
174
+ }
175
+ function walkOutlineSiblings(node, out, registry, resolver, sink, visited) {
176
+ let current = node;
177
+ while (current !== void 0) {
178
+ if (visited.has(current)) {
179
+ sink({
180
+ code: "pdf/outline-cycle",
181
+ severity: "warning",
182
+ message: "the outline contains a cycle; stopping the sibling chain at the repeated item"
183
+ });
184
+ return;
185
+ }
186
+ visited.add(current);
187
+ const titleObj = dictGet(current, "Title");
188
+ const children = [];
189
+ const childFirst = resolver.resolveDict(dictGet(current, "First"));
190
+ if (childFirst !== void 0) walkOutlineSiblings(childFirst, children, registry, resolver, sink, visited);
191
+ const destination = internOutlineDestination(current, registry, resolver);
192
+ out.push({
193
+ title: titleObj?.kind === "string" ? decodePdfString(titleObj.bytes) : "",
194
+ ...destination !== void 0 ? { destination } : {},
195
+ children
196
+ });
197
+ current = resolver.resolveDict(dictGet(current, "Next"));
198
+ }
199
+ }
200
+ function internOutlineDestination(node, registry, resolver) {
201
+ const dest = dictGet(node, "Dest");
202
+ if (dest !== void 0) return registry.intern(dest);
203
+ const action = resolver.resolveDict(dictGet(node, "A"));
204
+ if (action !== void 0 && asName(dictGet(action, "S")) === "GoTo") return registry.intern(dictGet(action, "D"));
205
+ }
206
+ //#endregion
207
+ export { createDestinationRegistry, parseDestination, readOutline };
@@ -0,0 +1,63 @@
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/optional-content.ts
5
+ function readOptionalContent(catalog, resolver, sink) {
6
+ const ocProperties = resolver.resolveDict(require_objects.dictGet(catalog, "OCProperties"));
7
+ if (ocProperties === void 0) return {
8
+ layers: [],
9
+ layerNameOf: () => void 0
10
+ };
11
+ const nameByGroup = /* @__PURE__ */ new Map();
12
+ const groups = [];
13
+ const ocgs = require_objects.asArray(resolver.resolve(require_objects.dictGet(ocProperties, "OCGs"))) ?? [];
14
+ for (const ocgRef of ocgs) {
15
+ const ocg = resolver.resolveDict(ocgRef);
16
+ if (ocg === void 0) {
17
+ sink({
18
+ code: "pdf/ocg-unresolved",
19
+ severity: "warning",
20
+ message: "an entry in /OCProperties /OCGs did not resolve to a dictionary; skipping it"
21
+ });
22
+ continue;
23
+ }
24
+ const nameObj = require_objects.dictGet(ocg, "Name");
25
+ const name = nameObj?.kind === "string" ? require_pdf_text.decodePdfString(nameObj.bytes) : mintLayerName(nameByGroup);
26
+ nameByGroup.set(ocg, name);
27
+ groups.push({
28
+ dict: ocg,
29
+ name
30
+ });
31
+ }
32
+ const defaultConfig = resolver.resolveDict(require_objects.dictGet(ocProperties, "D"));
33
+ const baseVisible = defaultConfig === void 0 || require_objects.asName(require_objects.dictGet(defaultConfig, "BaseState")) !== "OFF";
34
+ const groupsIn = (key) => {
35
+ const set = /* @__PURE__ */ new Set();
36
+ const arr = defaultConfig === void 0 ? void 0 : require_objects.asArray(resolver.resolve(require_objects.dictGet(defaultConfig, key)));
37
+ if (arr !== void 0) for (const entry of arr) {
38
+ const dict = resolver.resolveDict(entry);
39
+ if (dict !== void 0) set.add(dict);
40
+ }
41
+ return set;
42
+ };
43
+ const on = groupsIn("ON");
44
+ const off = groupsIn("OFF");
45
+ return {
46
+ layers: groups.map(({ dict, name }) => ({
47
+ name,
48
+ visible: off.has(dict) ? false : on.has(dict) ? true : baseVisible
49
+ })),
50
+ layerNameOf: (obj) => {
51
+ const dict = resolver.resolveDict(obj);
52
+ return dict !== void 0 ? nameByGroup.get(dict) : void 0;
53
+ }
54
+ };
55
+ }
56
+ function mintLayerName(taken) {
57
+ const used = new Set(taken.values());
58
+ let n = 1;
59
+ while (used.has(`layer${n}`)) n++;
60
+ return `layer${n}`;
61
+ }
62
+ //#endregion
63
+ exports.readOptionalContent = readOptionalContent;
@@ -0,0 +1,12 @@
1
+ import { PdfDiagnosticSink } from "./diagnostics.cjs";
2
+ import { PdfDict, PdfObject } from "./objects.cjs";
3
+ import { PdfObjectResolver } from "./interpret.cjs";
4
+ import { LayoutLayer } from "./layout.cjs";
5
+ //#region src/optional-content.d.ts
6
+ interface OptionalContentContext {
7
+ readonly layers: readonly LayoutLayer[];
8
+ readonly layerNameOf: (obj: PdfObject | undefined) => string | undefined;
9
+ }
10
+ declare function readOptionalContent(catalog: PdfDict, resolver: PdfObjectResolver, sink: PdfDiagnosticSink): OptionalContentContext;
11
+ //#endregion
12
+ export { OptionalContentContext, readOptionalContent };
@@ -0,0 +1,12 @@
1
+ import { PdfDiagnosticSink } from "./diagnostics.js";
2
+ import { PdfDict, PdfObject } from "./objects.js";
3
+ import { PdfObjectResolver } from "./interpret.js";
4
+ import { LayoutLayer } from "./layout.js";
5
+ //#region src/optional-content.d.ts
6
+ interface OptionalContentContext {
7
+ readonly layers: readonly LayoutLayer[];
8
+ readonly layerNameOf: (obj: PdfObject | undefined) => string | undefined;
9
+ }
10
+ declare function readOptionalContent(catalog: PdfDict, resolver: PdfObjectResolver, sink: PdfDiagnosticSink): OptionalContentContext;
11
+ //#endregion
12
+ export { OptionalContentContext, readOptionalContent };
@@ -0,0 +1,62 @@
1
+ import { asArray, asName, dictGet } from "./objects.js";
2
+ import { decodePdfString } from "./pdf-text.js";
3
+ //#region src/optional-content.ts
4
+ function readOptionalContent(catalog, resolver, sink) {
5
+ const ocProperties = resolver.resolveDict(dictGet(catalog, "OCProperties"));
6
+ if (ocProperties === void 0) return {
7
+ layers: [],
8
+ layerNameOf: () => void 0
9
+ };
10
+ const nameByGroup = /* @__PURE__ */ new Map();
11
+ const groups = [];
12
+ const ocgs = asArray(resolver.resolve(dictGet(ocProperties, "OCGs"))) ?? [];
13
+ for (const ocgRef of ocgs) {
14
+ const ocg = resolver.resolveDict(ocgRef);
15
+ if (ocg === void 0) {
16
+ sink({
17
+ code: "pdf/ocg-unresolved",
18
+ severity: "warning",
19
+ message: "an entry in /OCProperties /OCGs did not resolve to a dictionary; skipping it"
20
+ });
21
+ continue;
22
+ }
23
+ const nameObj = dictGet(ocg, "Name");
24
+ const name = nameObj?.kind === "string" ? decodePdfString(nameObj.bytes) : mintLayerName(nameByGroup);
25
+ nameByGroup.set(ocg, name);
26
+ groups.push({
27
+ dict: ocg,
28
+ name
29
+ });
30
+ }
31
+ const defaultConfig = resolver.resolveDict(dictGet(ocProperties, "D"));
32
+ const baseVisible = defaultConfig === void 0 || asName(dictGet(defaultConfig, "BaseState")) !== "OFF";
33
+ const groupsIn = (key) => {
34
+ const set = /* @__PURE__ */ new Set();
35
+ const arr = defaultConfig === void 0 ? void 0 : asArray(resolver.resolve(dictGet(defaultConfig, key)));
36
+ if (arr !== void 0) for (const entry of arr) {
37
+ const dict = resolver.resolveDict(entry);
38
+ if (dict !== void 0) set.add(dict);
39
+ }
40
+ return set;
41
+ };
42
+ const on = groupsIn("ON");
43
+ const off = groupsIn("OFF");
44
+ return {
45
+ layers: groups.map(({ dict, name }) => ({
46
+ name,
47
+ visible: off.has(dict) ? false : on.has(dict) ? true : baseVisible
48
+ })),
49
+ layerNameOf: (obj) => {
50
+ const dict = resolver.resolveDict(obj);
51
+ return dict !== void 0 ? nameByGroup.get(dict) : void 0;
52
+ }
53
+ };
54
+ }
55
+ function mintLayerName(taken) {
56
+ const used = new Set(taken.values());
57
+ let n = 1;
58
+ while (used.has(`layer${n}`)) n++;
59
+ return `layer${n}`;
60
+ }
61
+ //#endregion
62
+ export { readOptionalContent };
package/dist/parse.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_lexer = require("./lexer.cjs");
3
2
  const require_objects = require("./objects.cjs");
3
+ const require_lexer = require("./lexer.cjs");
4
4
  //#region src/parse.ts
5
5
  function parseValue(reader, sink) {
6
6
  const token = require_lexer.nextToken(reader);
package/dist/parse.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { ByteReader } from "./bytes/reader.cjs";
2
1
  import { PdfDiagnosticSink } from "./diagnostics.cjs";
3
2
  import { PdfObject } from "./objects.cjs";
3
+ import { ByteReader } from "./bytes/reader.cjs";
4
4
  //#region src/parse.d.ts
5
5
  declare function parseValue(reader: ByteReader, sink: PdfDiagnosticSink): PdfObject | undefined;
6
6
  interface ParsedIndirectObject {
package/dist/parse.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { ByteReader } from "./bytes/reader.js";
2
1
  import { PdfDiagnosticSink } from "./diagnostics.js";
3
2
  import { PdfObject } from "./objects.js";
3
+ import { ByteReader } from "./bytes/reader.js";
4
4
  //#region src/parse.d.ts
5
5
  declare function parseValue(reader: ByteReader, sink: PdfDiagnosticSink): PdfObject | undefined;
6
6
  interface ParsedIndirectObject {
package/dist/parse.js CHANGED
@@ -1,5 +1,5 @@
1
- import { nextToken } from "./lexer.js";
2
1
  import { dictGet, pdfArray, pdfBool, pdfDict, pdfHexString, pdfLiteralString, pdfName, pdfNull, pdfNum, pdfRef, pdfStream } from "./objects.js";
2
+ import { nextToken } from "./lexer.js";
3
3
  //#region src/parse.ts
4
4
  function parseValue(reader, sink) {
5
5
  const token = nextToken(reader);
@@ -0,0 +1,21 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/pdf-text.ts
3
+ function decodePdfString(bytes) {
4
+ if (bytes.length >= 2 && bytes[0] === 254 && bytes[1] === 255) {
5
+ let out = "";
6
+ for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode((bytes[i] ?? 0) << 8 | (bytes[i + 1] ?? 0));
7
+ return out;
8
+ }
9
+ return Array.from(bytes, (b) => String.fromCharCode(b)).join("");
10
+ }
11
+ const PDF_DATE_PATTERN = /^D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?([+\-Z])?(\d{2})?'?(\d{2})?'?$/;
12
+ function parsePdfDate(raw) {
13
+ if (raw === void 0) return;
14
+ const match = PDF_DATE_PATTERN.exec(raw);
15
+ if (match === null) return;
16
+ const [, year, month = "01", day = "01", hour = "00", minute = "00", second = "00", tzSign, tzHour = "00", tzMinute = "00"] = match;
17
+ return `${year}-${month}-${day}T${hour}:${minute}:${second}${tzSign === void 0 || tzSign === "Z" ? "Z" : `${tzSign}${tzHour}:${tzMinute}`}`;
18
+ }
19
+ //#endregion
20
+ exports.decodePdfString = decodePdfString;
21
+ exports.parsePdfDate = parsePdfDate;
@@ -0,0 +1,5 @@
1
+ //#region src/pdf-text.d.ts
2
+ declare function decodePdfString(bytes: Uint8Array<ArrayBuffer>): string;
3
+ declare function parsePdfDate(raw: string | undefined): string | undefined;
4
+ //#endregion
5
+ export { decodePdfString, parsePdfDate };
@@ -0,0 +1,5 @@
1
+ //#region src/pdf-text.d.ts
2
+ declare function decodePdfString(bytes: Uint8Array<ArrayBuffer>): string;
3
+ declare function parsePdfDate(raw: string | undefined): string | undefined;
4
+ //#endregion
5
+ export { decodePdfString, parsePdfDate };
@@ -0,0 +1,19 @@
1
+ //#region src/pdf-text.ts
2
+ function decodePdfString(bytes) {
3
+ if (bytes.length >= 2 && bytes[0] === 254 && bytes[1] === 255) {
4
+ let out = "";
5
+ for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode((bytes[i] ?? 0) << 8 | (bytes[i + 1] ?? 0));
6
+ return out;
7
+ }
8
+ return Array.from(bytes, (b) => String.fromCharCode(b)).join("");
9
+ }
10
+ const PDF_DATE_PATTERN = /^D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?([+\-Z])?(\d{2})?'?(\d{2})?'?$/;
11
+ function parsePdfDate(raw) {
12
+ if (raw === void 0) return;
13
+ const match = PDF_DATE_PATTERN.exec(raw);
14
+ if (match === null) return;
15
+ const [, year, month = "01", day = "01", hour = "00", minute = "00", second = "00", tzSign, tzHour = "00", tzMinute = "00"] = match;
16
+ return `${year}-${month}-${day}T${hour}:${minute}:${second}${tzSign === void 0 || tzSign === "Z" ? "Z" : `${tzSign}${tzHour}:${tzMinute}`}`;
17
+ }
18
+ //#endregion
19
+ export { decodePdfString, parsePdfDate };