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.
- package/README.md +2 -2
- package/dist/annotations.cjs +104 -0
- package/dist/annotations.d.cts +9 -0
- package/dist/annotations.d.ts +9 -0
- package/dist/annotations.js +103 -0
- package/dist/attachments.cjs +65 -0
- package/dist/attachments.d.cts +8 -0
- package/dist/attachments.d.ts +8 -0
- package/dist/attachments.js +64 -0
- package/dist/bytes/flate.cjs +1 -1
- package/dist/bytes/flate.js +1 -1
- package/dist/codec.d.cts +109 -0
- package/dist/codec.d.ts +109 -0
- package/dist/content-read.cjs +1 -1
- package/dist/content-read.js +1 -1
- package/dist/content-write.cjs +2 -2
- package/dist/content-write.js +2 -2
- package/dist/document.cjs +12 -3
- package/dist/document.d.cts +2 -0
- package/dist/document.d.ts +2 -0
- package/dist/document.js +12 -3
- package/dist/embedded-font-write.cjs +1 -1
- package/dist/embedded-font-write.js +1 -1
- package/dist/encrypt.cjs +1 -1
- package/dist/encrypt.js +1 -1
- package/dist/filters.cjs +1 -1
- package/dist/filters.js +1 -1
- package/dist/font-read.cjs +1 -1
- package/dist/font-read.js +1 -1
- package/dist/font-registry.cjs +1 -1
- package/dist/font-registry.js +1 -1
- package/dist/form.cjs +138 -0
- package/dist/form.d.cts +9 -0
- package/dist/form.d.ts +9 -0
- package/dist/form.js +137 -0
- package/dist/image/png-decode.cjs +1 -1
- package/dist/image/png-decode.js +1 -1
- package/dist/image/png-encode.cjs +1 -1
- package/dist/image/png-encode.js +1 -1
- package/dist/index.cjs +12 -2
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/interpret.cjs +70 -10
- package/dist/interpret.d.cts +9 -1
- package/dist/interpret.d.ts +9 -1
- package/dist/interpret.js +70 -10
- package/dist/layout.cjs +132 -2
- package/dist/layout.d.cts +335 -1
- package/dist/layout.d.ts +335 -1
- package/dist/layout.js +124 -4
- package/dist/math-content-write.cjs +1 -1
- package/dist/math-content-write.js +1 -1
- package/dist/math-font.cjs +1 -1
- package/dist/math-font.js +1 -1
- package/dist/names.cjs +41 -0
- package/dist/names.d.cts +11 -0
- package/dist/names.d.ts +11 -0
- package/dist/names.js +40 -0
- package/dist/navigation.cjs +210 -0
- package/dist/navigation.d.cts +18 -0
- package/dist/navigation.d.ts +18 -0
- package/dist/navigation.js +207 -0
- package/dist/optional-content.cjs +63 -0
- package/dist/optional-content.d.cts +12 -0
- package/dist/optional-content.d.ts +12 -0
- package/dist/optional-content.js +62 -0
- package/dist/parse.cjs +1 -1
- package/dist/parse.d.cts +1 -1
- package/dist/parse.d.ts +1 -1
- package/dist/parse.js +1 -1
- package/dist/pdf-text.cjs +21 -0
- package/dist/pdf-text.d.cts +5 -0
- package/dist/pdf-text.d.ts +5 -0
- package/dist/pdf-text.js +19 -0
- package/dist/read.cjs +128 -58
- package/dist/read.d.cts +2 -4
- package/dist/read.d.ts +2 -4
- package/dist/read.js +125 -53
- package/dist/serialize.cjs +5 -1
- package/dist/serialize.d.cts +3 -2
- package/dist/serialize.d.ts +3 -2
- package/dist/serialize.js +5 -2
- package/dist/write.cjs +51 -5
- package/dist/write.js +51 -5
- package/dist/xmp.cjs +46 -0
- package/dist/xmp.d.cts +14 -0
- package/dist/xmp.d.ts +14 -0
- package/dist/xmp.js +45 -0
- package/dist/xref.cjs +2 -2
- package/dist/xref.js +2 -2
- package/package.json +2 -2
package/dist/read.js
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
|
+
import "./notes-annotation-author.js";
|
|
2
|
+
import { asArray, asName, asNumber, dictGet, pdfArray, pdfNull } from "./objects.js";
|
|
3
|
+
import { decodePdfString, parsePdfDate } from "./pdf-text.js";
|
|
4
|
+
import { concatBytes } from "./bytes/writer.js";
|
|
5
|
+
import { serializeObjectToText } from "./serialize.js";
|
|
6
|
+
import { applyMatrix, matrixRotationDegrees, matrixScaleX, matrixScaleY, multiplyMatrices, translationMatrix } from "./matrix.js";
|
|
7
|
+
import { readPageAnnotations } from "./annotations.js";
|
|
8
|
+
import { decodeStream } from "./filters.js";
|
|
1
9
|
import { bytesToBase64 } from "./util/base64.js";
|
|
10
|
+
import { readAttachments } from "./attachments.js";
|
|
2
11
|
import { crc32 } from "./bytes/crc32.js";
|
|
3
|
-
import {
|
|
12
|
+
import { readAcroForm } from "./form.js";
|
|
13
|
+
import { readXmpMetadata } from "./xmp.js";
|
|
14
|
+
import { readOptionalContent } from "./optional-content.js";
|
|
4
15
|
import "./layout.js";
|
|
5
16
|
import { NOOP_DIAGNOSTIC_SINK, PdfParseError } from "./diagnostics.js";
|
|
6
|
-
import { asArray, asName, asNumber, dictGet } from "./objects.js";
|
|
7
|
-
import { decodeStream } from "./filters.js";
|
|
8
17
|
import { openPdfDocument } from "./document.js";
|
|
9
18
|
import { throwIfAborted } from "./util/abort.js";
|
|
10
19
|
import { createFontResolver } from "./font-read.js";
|
|
11
20
|
import { readImageXObject } from "./images-read.js";
|
|
12
|
-
import { applyMatrix, matrixRotationDegrees, matrixScaleX, matrixScaleY, multiplyMatrices, translationMatrix } from "./matrix.js";
|
|
13
21
|
import { interpretContentStream } from "./interpret.js";
|
|
14
|
-
import "./
|
|
22
|
+
import { createDestinationRegistry, readOutline } from "./navigation.js";
|
|
15
23
|
//#region src/read.ts
|
|
16
24
|
const PDF_HEADER_BYTES = new TextEncoder().encode("%PDF-");
|
|
17
25
|
const HEADER_SEARCH_WINDOW = 1024;
|
|
@@ -37,15 +45,28 @@ function readPdf(bytes, options) {
|
|
|
37
45
|
});
|
|
38
46
|
const images = {};
|
|
39
47
|
const imageIdCache = /* @__PURE__ */ new Map();
|
|
40
|
-
const
|
|
48
|
+
const pageDicts = doc.pages();
|
|
49
|
+
const destinationRegistry = createDestinationRegistry(doc.catalog, doc, (obj) => doc.pageIndex(obj), sink);
|
|
50
|
+
const outline = readOutline(doc.catalog, destinationRegistry, doc, sink);
|
|
51
|
+
const attachments = readAttachments(doc.catalog, pageDicts, doc, sink);
|
|
52
|
+
const optionalContent = readOptionalContent(doc.catalog, doc, sink);
|
|
53
|
+
const form = readAcroForm(doc.catalog, doc, (obj) => doc.pageIndex(obj), sink);
|
|
54
|
+
const source = readDocumentResidue(doc, sink);
|
|
55
|
+
const pages = pageDicts.map((pageDict) => {
|
|
41
56
|
throwIfAborted(signal);
|
|
42
|
-
return readPage(pageDict, doc, fontResolver, images, imageIdCache, sink);
|
|
57
|
+
return readPage(pageDict, doc, fontResolver, images, imageIdCache, destinationRegistry, optionalContent.layerNameOf, sink);
|
|
43
58
|
});
|
|
44
59
|
return {
|
|
45
60
|
formatVersion: 1,
|
|
46
|
-
metadata: readMetadata(doc.trailer, doc),
|
|
61
|
+
metadata: readMetadata(doc.trailer, doc, doc.catalog, sink),
|
|
47
62
|
pages,
|
|
48
|
-
images
|
|
63
|
+
images,
|
|
64
|
+
...destinationRegistry.entries.length > 0 ? { destinations: [...destinationRegistry.entries] } : {},
|
|
65
|
+
...outline.length > 0 ? { outline } : {},
|
|
66
|
+
...attachments.length > 0 ? { attachments } : {},
|
|
67
|
+
...optionalContent.layers.length > 0 ? { layers: [...optionalContent.layers] } : {},
|
|
68
|
+
...form.length > 0 ? { form } : {},
|
|
69
|
+
...Object.keys(source).length > 0 ? { source } : {}
|
|
49
70
|
};
|
|
50
71
|
}
|
|
51
72
|
function readMediaBox(page) {
|
|
@@ -135,7 +156,7 @@ function readPageContentBytes(page, resolver, sink) {
|
|
|
135
156
|
}
|
|
136
157
|
return /* @__PURE__ */ new Uint8Array(0);
|
|
137
158
|
}
|
|
138
|
-
function readPage(page, resolver, fontResolver, images, imageIdCache, sink) {
|
|
159
|
+
function readPage(page, resolver, fontResolver, images, imageIdCache, destinationRegistry, layerNameOf, sink) {
|
|
139
160
|
const resources = resolver.resolveDict(dictGet(page, "Resources"));
|
|
140
161
|
const mediaBox = readMediaBox(page);
|
|
141
162
|
const rotationResult = pageRotationTransform(normalizeRotation(asNumber(dictGet(page, "Rotate"))), mediaBox.urx - mediaBox.llx, mediaBox.ury - mediaBox.lly);
|
|
@@ -146,7 +167,8 @@ function readPage(page, resolver, fontResolver, images, imageIdCache, sink) {
|
|
|
146
167
|
const extracted = interpretContentStream(contentBytes, resources, {
|
|
147
168
|
fontMetrics: fontResolver.metrics,
|
|
148
169
|
resolver,
|
|
149
|
-
sink
|
|
170
|
+
sink,
|
|
171
|
+
layerNameOf
|
|
150
172
|
});
|
|
151
173
|
for (const item of extracted) {
|
|
152
174
|
const converted = convertExtractedItem(item, pageMatrix, fontResolver, images, imageIdCache, resolver, sink);
|
|
@@ -157,13 +179,15 @@ function readPage(page, resolver, fontResolver, images, imageIdCache, sink) {
|
|
|
157
179
|
severity: "warning",
|
|
158
180
|
message: "page has no /Resources dict; its content stream cannot be interpreted"
|
|
159
181
|
});
|
|
160
|
-
items.push(...readLinkAnnotations(page, pageMatrix, resolver));
|
|
182
|
+
items.push(...readLinkAnnotations(page, pageMatrix, resolver, destinationRegistry));
|
|
161
183
|
const notes = readPageNotes(page, resolver);
|
|
184
|
+
const annotations = readPageAnnotations(page, pageMatrix, resolver, sink);
|
|
162
185
|
return {
|
|
163
186
|
widthPt: rotationResult.widthPt,
|
|
164
187
|
heightPt: rotationResult.heightPt,
|
|
165
188
|
items,
|
|
166
|
-
...notes !== void 0 ? { notes } : {}
|
|
189
|
+
...notes !== void 0 ? { notes } : {},
|
|
190
|
+
...annotations.length > 0 ? { annotations } : {}
|
|
167
191
|
};
|
|
168
192
|
}
|
|
169
193
|
function convertExtractedItem(item, pageMatrix, fontResolver, images, imageIdCache, resolver, sink) {
|
|
@@ -198,7 +222,10 @@ function convertText(item, pageMatrix, fontResolver) {
|
|
|
198
222
|
sizePt: sizePt > 0 ? sizePt : item.sizePt,
|
|
199
223
|
color: item.color,
|
|
200
224
|
widthPt,
|
|
201
|
-
rotationDeg: rotationDeg !== 0 ? rotationDeg : void 0
|
|
225
|
+
rotationDeg: rotationDeg !== 0 ? rotationDeg : void 0,
|
|
226
|
+
...item.layerName !== void 0 ? { layer: item.layerName } : {},
|
|
227
|
+
...item.actualText !== void 0 ? { actualText: item.actualText } : {},
|
|
228
|
+
...item.alt !== void 0 ? { alt: item.alt } : {}
|
|
202
229
|
};
|
|
203
230
|
}
|
|
204
231
|
function paintFields(paint) {
|
|
@@ -227,14 +254,16 @@ function convertRect(item, pageMatrix) {
|
|
|
227
254
|
return {
|
|
228
255
|
kind: "rect",
|
|
229
256
|
...transformBox(item, pageMatrix),
|
|
230
|
-
...paintFields(item)
|
|
257
|
+
...paintFields(item),
|
|
258
|
+
...item.layerName !== void 0 ? { layer: item.layerName } : {}
|
|
231
259
|
};
|
|
232
260
|
}
|
|
233
261
|
function convertEllipse(item, pageMatrix) {
|
|
234
262
|
return {
|
|
235
263
|
kind: "ellipse",
|
|
236
264
|
...transformBox(item, pageMatrix),
|
|
237
|
-
...paintFields(item)
|
|
265
|
+
...paintFields(item),
|
|
266
|
+
...item.layerName !== void 0 ? { layer: item.layerName } : {}
|
|
238
267
|
};
|
|
239
268
|
}
|
|
240
269
|
function convertLine(item, pageMatrix) {
|
|
@@ -253,7 +282,8 @@ function convertLine(item, pageMatrix) {
|
|
|
253
282
|
x2Pt: p2.x,
|
|
254
283
|
y2Pt: p2.y,
|
|
255
284
|
color: item.color,
|
|
256
|
-
widthPt: item.widthPt
|
|
285
|
+
widthPt: item.widthPt,
|
|
286
|
+
...item.layerName !== void 0 ? { layer: item.layerName } : {}
|
|
257
287
|
};
|
|
258
288
|
}
|
|
259
289
|
function transformSubpath(subpath, pageMatrix) {
|
|
@@ -308,7 +338,8 @@ function convertPath(item, pageMatrix) {
|
|
|
308
338
|
subpaths: item.subpaths.map((subpath) => transformSubpath(subpath, pageMatrix)),
|
|
309
339
|
...item.fill !== void 0 ? { fill: item.fill } : {},
|
|
310
340
|
...item.fill !== void 0 && item.fillRule === "evenodd" ? { fillRule: "evenodd" } : {},
|
|
311
|
-
...item.stroke !== void 0 ? { stroke: item.stroke } : {}
|
|
341
|
+
...item.stroke !== void 0 ? { stroke: item.stroke } : {},
|
|
342
|
+
...item.layerName !== void 0 ? { layer: item.layerName } : {}
|
|
312
343
|
};
|
|
313
344
|
}
|
|
314
345
|
function imagePlacementFrom(matrix) {
|
|
@@ -351,7 +382,8 @@ function convertImage(item, pageMatrix, images, cache, resolver, sink) {
|
|
|
351
382
|
return {
|
|
352
383
|
kind: "image",
|
|
353
384
|
imageId,
|
|
354
|
-
...imagePlacementFrom(multiplyMatrices(item.matrix, pageMatrix))
|
|
385
|
+
...imagePlacementFrom(multiplyMatrices(item.matrix, pageMatrix)),
|
|
386
|
+
...item.layerName !== void 0 ? { layer: item.layerName } : {}
|
|
355
387
|
};
|
|
356
388
|
}
|
|
357
389
|
function convertInlineImage(item, pageMatrix, images, resolver, sink) {
|
|
@@ -360,19 +392,22 @@ function convertInlineImage(item, pageMatrix, images, resolver, sink) {
|
|
|
360
392
|
return {
|
|
361
393
|
kind: "image",
|
|
362
394
|
imageId: registerExtractedImage(decoded.format, decoded.bytes, decoded.widthPx, decoded.heightPx, images),
|
|
363
|
-
...imagePlacementFrom(multiplyMatrices(item.matrix, pageMatrix))
|
|
395
|
+
...imagePlacementFrom(multiplyMatrices(item.matrix, pageMatrix)),
|
|
396
|
+
...item.layerName !== void 0 ? { layer: item.layerName } : {}
|
|
364
397
|
};
|
|
365
398
|
}
|
|
366
|
-
function readLinkAnnotations(page, pageMatrix, resolver) {
|
|
399
|
+
function readLinkAnnotations(page, pageMatrix, resolver, destinationRegistry) {
|
|
367
400
|
const annotsArr = asArray(dictGet(page, "Annots"));
|
|
368
401
|
if (annotsArr === void 0) return [];
|
|
369
402
|
const links = [];
|
|
370
403
|
for (const annotRef of annotsArr) {
|
|
371
404
|
const annot = resolver.resolveDict(annotRef);
|
|
372
405
|
if (annot === void 0 || asName(dictGet(annot, "Subtype")) !== "Link") continue;
|
|
373
|
-
const uri = readLinkUri(annot, resolver);
|
|
374
406
|
const rectArr = asArray(dictGet(annot, "Rect"));
|
|
375
|
-
if (
|
|
407
|
+
if (rectArr === void 0) continue;
|
|
408
|
+
const uri = readLinkUri(annot, resolver);
|
|
409
|
+
const destination = uri === void 0 ? readInternalDestination(annot, resolver, destinationRegistry) : void 0;
|
|
410
|
+
if (uri === void 0 && destination === void 0) continue;
|
|
376
411
|
const x1 = asNumber(rectArr[0]) ?? 0;
|
|
377
412
|
const y1 = asNumber(rectArr[1]) ?? 0;
|
|
378
413
|
const x2 = asNumber(rectArr[2]) ?? 0;
|
|
@@ -385,13 +420,24 @@ function readLinkAnnotations(page, pageMatrix, resolver) {
|
|
|
385
420
|
x: Math.max(x1, x2),
|
|
386
421
|
y: Math.max(y1, y2)
|
|
387
422
|
});
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
423
|
+
const contentsObj = dictGet(annot, "Contents");
|
|
424
|
+
const title = contentsObj?.kind === "string" ? decodePdfString(contentsObj.bytes) : void 0;
|
|
425
|
+
const box = {
|
|
391
426
|
xPt: Math.min(p1.x, p2.x),
|
|
392
427
|
yPt: Math.min(p1.y, p2.y),
|
|
393
428
|
widthPt: Math.abs(p2.x - p1.x),
|
|
394
|
-
heightPt: Math.abs(p2.y - p1.y)
|
|
429
|
+
heightPt: Math.abs(p2.y - p1.y),
|
|
430
|
+
...title !== void 0 ? { title } : {}
|
|
431
|
+
};
|
|
432
|
+
if (uri !== void 0) links.push({
|
|
433
|
+
kind: "link",
|
|
434
|
+
uri,
|
|
435
|
+
...box
|
|
436
|
+
});
|
|
437
|
+
else if (destination !== void 0) links.push({
|
|
438
|
+
kind: "internalLink",
|
|
439
|
+
destination,
|
|
440
|
+
...box
|
|
395
441
|
});
|
|
396
442
|
}
|
|
397
443
|
return links;
|
|
@@ -402,6 +448,12 @@ function readLinkUri(annot, resolver) {
|
|
|
402
448
|
const uriObj = dictGet(action, "URI");
|
|
403
449
|
return uriObj?.kind === "string" ? decodePdfString(uriObj.bytes) : void 0;
|
|
404
450
|
}
|
|
451
|
+
function readInternalDestination(annot, resolver, destinationRegistry) {
|
|
452
|
+
const dest = dictGet(annot, "Dest");
|
|
453
|
+
if (dest !== void 0) return destinationRegistry.intern(dest);
|
|
454
|
+
const action = resolver.resolveDict(dictGet(annot, "A"));
|
|
455
|
+
if (action !== void 0 && asName(dictGet(action, "S")) === "GoTo") return destinationRegistry.intern(dictGet(action, "D"));
|
|
456
|
+
}
|
|
405
457
|
function readPageNotes(page, resolver) {
|
|
406
458
|
const annotsArr = asArray(dictGet(page, "Annots"));
|
|
407
459
|
if (annotsArr === void 0) return;
|
|
@@ -414,23 +466,7 @@ function readPageNotes(page, resolver) {
|
|
|
414
466
|
if (contentsObj?.kind === "string") return decodePdfString(contentsObj.bytes);
|
|
415
467
|
}
|
|
416
468
|
}
|
|
417
|
-
function
|
|
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) {
|
|
469
|
+
function readMetadata(trailer, resolver, catalog, sink) {
|
|
434
470
|
const info = resolver.resolveDict(dictGet(trailer, "Info"));
|
|
435
471
|
if (info === void 0) return {};
|
|
436
472
|
const stringField = (key) => {
|
|
@@ -438,16 +474,52 @@ function readMetadata(trailer, resolver) {
|
|
|
438
474
|
return obj?.kind === "string" ? decodePdfString(obj.bytes) : void 0;
|
|
439
475
|
};
|
|
440
476
|
const keywords = stringField("Keywords")?.split(",").map((k) => k.trim()).filter((k) => k.length > 0);
|
|
477
|
+
const langObj = dictGet(catalog, "Lang");
|
|
478
|
+
const xmp = xmpPacket(catalog, resolver, sink);
|
|
479
|
+
const mirrored = readXmpMetadata(xmp ?? "");
|
|
441
480
|
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"))
|
|
481
|
+
title: stringField("Title") ?? mirrored.title,
|
|
482
|
+
author: stringField("Author") ?? mirrored.author,
|
|
483
|
+
subject: stringField("Subject") ?? mirrored.subject,
|
|
484
|
+
keywords: (keywords !== void 0 && keywords.length > 0 ? keywords : void 0) ?? mirrored.keywords,
|
|
485
|
+
creator: stringField("Creator") ?? mirrored.creator,
|
|
486
|
+
producer: stringField("Producer") ?? mirrored.producer,
|
|
487
|
+
createdIso: parsePdfDate(stringField("CreationDate")) ?? mirrored.createdIso,
|
|
488
|
+
modifiedIso: parsePdfDate(stringField("ModDate")) ?? mirrored.modifiedIso,
|
|
489
|
+
...langObj?.kind === "string" ? { language: decodePdfString(langObj.bytes) } : {}
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
function xmpPacket(catalog, resolver, sink) {
|
|
493
|
+
const metadataObj = resolver.resolve(dictGet(catalog, "Metadata"));
|
|
494
|
+
if (metadataObj?.kind !== "stream") return;
|
|
495
|
+
const decoded = decodeStream(metadataObj.raw, metadataObj.dict, sink);
|
|
496
|
+
return new TextDecoder().decode(decoded.bytes);
|
|
497
|
+
}
|
|
498
|
+
function readDocumentResidue(doc, sink) {
|
|
499
|
+
const source = {};
|
|
500
|
+
const residue = (key, obj) => {
|
|
501
|
+
if (obj !== void 0) source[key] = {
|
|
502
|
+
format: "pdf",
|
|
503
|
+
xml: serializeObjectToText(obj)
|
|
504
|
+
};
|
|
505
|
+
};
|
|
506
|
+
const catalog = doc.catalog;
|
|
507
|
+
const packet = xmpPacket(catalog, doc, sink);
|
|
508
|
+
if (packet !== void 0) source.xmp = {
|
|
509
|
+
format: "pdf",
|
|
510
|
+
xml: packet
|
|
450
511
|
};
|
|
512
|
+
residue("viewer-preferences", dictGet(catalog, "ViewerPreferences"));
|
|
513
|
+
residue("page-mode", dictGet(catalog, "PageMode"));
|
|
514
|
+
residue("page-layout", dictGet(catalog, "PageLayout"));
|
|
515
|
+
residue("open-action", dictGet(catalog, "OpenAction"));
|
|
516
|
+
const outputIntents = asArray(dictGet(catalog, "OutputIntents"));
|
|
517
|
+
if (outputIntents !== void 0) residue("output-intents", pdfArray(outputIntents.map((intent) => doc.resolve(intent) ?? pdfNull())));
|
|
518
|
+
residue("piece-info", dictGet(catalog, "PieceInfo"));
|
|
519
|
+
residue("legal", dictGet(catalog, "Legal"));
|
|
520
|
+
residue("collection", dictGet(catalog, "Collection"));
|
|
521
|
+
residue("trailer-id", dictGet(doc.trailer, "ID"));
|
|
522
|
+
return source;
|
|
451
523
|
}
|
|
452
524
|
//#endregion
|
|
453
|
-
export {
|
|
525
|
+
export { normalizeRotation, pageRotationTransform, readPdf };
|
package/dist/serialize.cjs
CHANGED
|
@@ -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
|
//#region src/serialize.ts
|
|
5
5
|
const NUMBER_DECIMAL_PLACES = 4;
|
|
6
6
|
const NUMBER_EPSILON = 10 ** -4;
|
|
@@ -63,7 +63,11 @@ function serializeObject(obj) {
|
|
|
63
63
|
writeObject(writer, obj);
|
|
64
64
|
return writer.toBytes();
|
|
65
65
|
}
|
|
66
|
+
function serializeObjectToText(obj) {
|
|
67
|
+
return new TextDecoder().decode(serializeObject(obj));
|
|
68
|
+
}
|
|
66
69
|
//#endregion
|
|
67
70
|
exports.formatNumber = formatNumber;
|
|
68
71
|
exports.serializeObject = serializeObject;
|
|
72
|
+
exports.serializeObjectToText = serializeObjectToText;
|
|
69
73
|
exports.writeObject = writeObject;
|
package/dist/serialize.d.cts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { ByteWriter } from "./bytes/writer.cjs";
|
|
2
1
|
import { PdfObject } from "./objects.cjs";
|
|
2
|
+
import { ByteWriter } from "./bytes/writer.cjs";
|
|
3
3
|
//#region src/serialize.d.ts
|
|
4
4
|
declare function formatNumber(n: number): string;
|
|
5
5
|
declare function writeObject(writer: ByteWriter, obj: PdfObject): void;
|
|
6
6
|
declare function serializeObject(obj: PdfObject): Uint8Array<ArrayBuffer>;
|
|
7
|
+
declare function serializeObjectToText(obj: PdfObject): string;
|
|
7
8
|
//#endregion
|
|
8
|
-
export { formatNumber, serializeObject, writeObject };
|
|
9
|
+
export { formatNumber, serializeObject, serializeObjectToText, writeObject };
|
package/dist/serialize.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { ByteWriter } from "./bytes/writer.js";
|
|
2
1
|
import { PdfObject } from "./objects.js";
|
|
2
|
+
import { ByteWriter } from "./bytes/writer.js";
|
|
3
3
|
//#region src/serialize.d.ts
|
|
4
4
|
declare function formatNumber(n: number): string;
|
|
5
5
|
declare function writeObject(writer: ByteWriter, obj: PdfObject): void;
|
|
6
6
|
declare function serializeObject(obj: PdfObject): Uint8Array<ArrayBuffer>;
|
|
7
|
+
declare function serializeObjectToText(obj: PdfObject): string;
|
|
7
8
|
//#endregion
|
|
8
|
-
export { formatNumber, serializeObject, writeObject };
|
|
9
|
+
export { formatNumber, serializeObject, serializeObjectToText, writeObject };
|
package/dist/serialize.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ByteWriter } from "./bytes/writer.js";
|
|
2
1
|
import { pdfNum } from "./objects.js";
|
|
2
|
+
import { ByteWriter } from "./bytes/writer.js";
|
|
3
3
|
//#region src/serialize.ts
|
|
4
4
|
const NUMBER_DECIMAL_PLACES = 4;
|
|
5
5
|
const NUMBER_EPSILON = 10 ** -4;
|
|
@@ -62,5 +62,8 @@ function serializeObject(obj) {
|
|
|
62
62
|
writeObject(writer, obj);
|
|
63
63
|
return writer.toBytes();
|
|
64
64
|
}
|
|
65
|
+
function serializeObjectToText(obj) {
|
|
66
|
+
return new TextDecoder().decode(serializeObject(obj));
|
|
67
|
+
}
|
|
65
68
|
//#endregion
|
|
66
|
-
export { formatNumber, serializeObject, writeObject };
|
|
69
|
+
export { formatNumber, serializeObject, serializeObjectToText, writeObject };
|
package/dist/write.cjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_afm_widths = require("./afm-widths-BoeTOK2r.cjs");
|
|
3
|
-
const
|
|
4
|
-
const require_bytes_writer = require("./bytes/writer.cjs");
|
|
3
|
+
const require_notes_annotation_author = require("./notes-annotation-author.cjs");
|
|
5
4
|
const require_objects = require("./objects.cjs");
|
|
5
|
+
const require_bytes_writer = require("./bytes/writer.cjs");
|
|
6
|
+
const require_serialize = require("./serialize.cjs");
|
|
6
7
|
const require_bytes_flate = require("./bytes/flate.cjs");
|
|
8
|
+
const require_util_base64 = require("./util/base64.cjs");
|
|
7
9
|
const require_util_abort = require("./util/abort.cjs");
|
|
8
10
|
const require_image_jpeg_info = require("./image/jpeg-info.cjs");
|
|
9
|
-
const require_notes_annotation_author = require("./notes-annotation-author.cjs");
|
|
10
11
|
const require_image_png_decode = require("./image/png-decode.cjs");
|
|
11
12
|
const require_embedded_font = require("./embedded-font.cjs");
|
|
12
|
-
const require_serialize = require("./serialize.cjs");
|
|
13
13
|
const require_content_write = require("./content-write.cjs");
|
|
14
14
|
const require_embedded_font_write = require("./embedded-font-write.cjs");
|
|
15
15
|
const require_font_registry = require("./font-registry.cjs");
|
|
@@ -178,9 +178,55 @@ function buildLinkAnnotDict(link) {
|
|
|
178
178
|
})
|
|
179
179
|
});
|
|
180
180
|
}
|
|
181
|
+
function destinationViewArray(target) {
|
|
182
|
+
const n = (value) => value === void 0 ? require_objects.pdfNull() : require_objects.pdfNum(value);
|
|
183
|
+
if (target.kind === "xyz") return [
|
|
184
|
+
require_objects.pdfName("XYZ"),
|
|
185
|
+
n(target.leftPt),
|
|
186
|
+
n(target.topPt),
|
|
187
|
+
n(target.zoom)
|
|
188
|
+
];
|
|
189
|
+
if (target.kind === "fitH") return [require_objects.pdfName("FitH"), n(target.topPt)];
|
|
190
|
+
if (target.kind === "fitV") return [require_objects.pdfName("FitV"), n(target.leftPt)];
|
|
191
|
+
if (target.kind === "fitR") return [
|
|
192
|
+
require_objects.pdfName("FitR"),
|
|
193
|
+
n(target.leftPt),
|
|
194
|
+
n(target.bottomPt),
|
|
195
|
+
n(target.rightPt),
|
|
196
|
+
n(target.topPt)
|
|
197
|
+
];
|
|
198
|
+
if (target.kind === "fitBH") return [require_objects.pdfName("FitBH"), n(target.topPt)];
|
|
199
|
+
if (target.kind === "fitBV") return [require_objects.pdfName("FitBV"), n(target.leftPt)];
|
|
200
|
+
return [require_objects.pdfName(target.kind === "fitB" ? "FitB" : "Fit")];
|
|
201
|
+
}
|
|
202
|
+
function buildInternalLinkAnnotDict(link, doc, pageAllocs) {
|
|
203
|
+
const destination = doc.destinations?.find((d) => d.name === link.destination);
|
|
204
|
+
if (destination === void 0) throw new Error(`internal link names destination "${link.destination}", which the document's destinations table does not carry -- this is a caller-invariant violation`);
|
|
205
|
+
const targetPage = pageAllocs[destination.pageIndex];
|
|
206
|
+
if (targetPage === void 0) throw new Error(`destination "${link.destination}" names page index ${destination.pageIndex}, which is beyond the document's own pages -- this is a caller-invariant violation`);
|
|
207
|
+
return require_objects.pdfDict({
|
|
208
|
+
Type: require_objects.pdfName("Annot"),
|
|
209
|
+
Subtype: require_objects.pdfName("Link"),
|
|
210
|
+
Rect: require_objects.pdfArray([
|
|
211
|
+
link.xPt,
|
|
212
|
+
link.yPt,
|
|
213
|
+
link.xPt + link.widthPt,
|
|
214
|
+
link.yPt + link.heightPt
|
|
215
|
+
].map((v) => require_objects.pdfNum(v))),
|
|
216
|
+
Border: require_objects.pdfArray([
|
|
217
|
+
0,
|
|
218
|
+
0,
|
|
219
|
+
0
|
|
220
|
+
].map((v) => require_objects.pdfNum(v))),
|
|
221
|
+
Dest: require_objects.pdfArray([require_objects.pdfRef(targetPage.pageNum, 0), ...destinationViewArray(destination.target)])
|
|
222
|
+
});
|
|
223
|
+
}
|
|
181
224
|
function isLinkItem(item) {
|
|
182
225
|
return item.kind === "link";
|
|
183
226
|
}
|
|
227
|
+
function isInternalLinkItem(item) {
|
|
228
|
+
return item.kind === "internalLink";
|
|
229
|
+
}
|
|
184
230
|
const NOTES_ANNOTATION_HIDDEN_FLAG = 2;
|
|
185
231
|
function buildNotesAnnotDict(notes) {
|
|
186
232
|
return require_objects.pdfDict({
|
|
@@ -436,7 +482,7 @@ function writePdf(doc, options = {}) {
|
|
|
436
482
|
num: contentsNum,
|
|
437
483
|
value: require_objects.pdfStream(contentsDict, finalContentBytes)
|
|
438
484
|
});
|
|
439
|
-
const annots = page.items.filter(isLinkItem).map((link) => buildLinkAnnotDict(link));
|
|
485
|
+
const annots = [...page.items.filter(isLinkItem).map((link) => buildLinkAnnotDict(link)), ...page.items.filter(isInternalLinkItem).map((link) => buildInternalLinkAnnotDict(link, doc, pageAllocs))];
|
|
440
486
|
if (page.notes !== void 0 && page.notes.length > 0) annots.push(buildNotesAnnotDict(page.notes));
|
|
441
487
|
const pageEntries = /* @__PURE__ */ new Map([
|
|
442
488
|
["Type", require_objects.pdfName("Page")],
|
package/dist/write.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { a as winAnsiGlyphName, n as widthOfCode, t as STANDARD_METRICS } from "./afm-widths-Dxucrg7D.js";
|
|
2
|
-
import {
|
|
2
|
+
import { NOTES_ANNOTATION_AUTHOR } from "./notes-annotation-author.js";
|
|
3
|
+
import { pdfArray, pdfDict, pdfHexString, pdfName, pdfNull, pdfNum, pdfRef, pdfStream } from "./objects.js";
|
|
3
4
|
import { ByteWriter, concatBytes } from "./bytes/writer.js";
|
|
4
|
-
import {
|
|
5
|
+
import { writeObject } from "./serialize.js";
|
|
5
6
|
import { deflate } from "./bytes/flate.js";
|
|
7
|
+
import { base64ToBytes } from "./util/base64.js";
|
|
6
8
|
import { throwIfAborted } from "./util/abort.js";
|
|
7
9
|
import { readJpegInfo } from "./image/jpeg-info.js";
|
|
8
|
-
import { NOTES_ANNOTATION_AUTHOR } from "./notes-annotation-author.js";
|
|
9
10
|
import { decodePng } from "./image/png-decode.js";
|
|
10
11
|
import { collectEmbeddedGlyphs } from "./embedded-font.js";
|
|
11
|
-
import { writeObject } from "./serialize.js";
|
|
12
12
|
import { writeContentStream } from "./content-write.js";
|
|
13
13
|
import { buildEmbeddedFontObjects } from "./embedded-font-write.js";
|
|
14
14
|
import { resolveFaceWithRegistry } from "./font-registry.js";
|
|
@@ -177,9 +177,55 @@ function buildLinkAnnotDict(link) {
|
|
|
177
177
|
})
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
|
+
function destinationViewArray(target) {
|
|
181
|
+
const n = (value) => value === void 0 ? pdfNull() : pdfNum(value);
|
|
182
|
+
if (target.kind === "xyz") return [
|
|
183
|
+
pdfName("XYZ"),
|
|
184
|
+
n(target.leftPt),
|
|
185
|
+
n(target.topPt),
|
|
186
|
+
n(target.zoom)
|
|
187
|
+
];
|
|
188
|
+
if (target.kind === "fitH") return [pdfName("FitH"), n(target.topPt)];
|
|
189
|
+
if (target.kind === "fitV") return [pdfName("FitV"), n(target.leftPt)];
|
|
190
|
+
if (target.kind === "fitR") return [
|
|
191
|
+
pdfName("FitR"),
|
|
192
|
+
n(target.leftPt),
|
|
193
|
+
n(target.bottomPt),
|
|
194
|
+
n(target.rightPt),
|
|
195
|
+
n(target.topPt)
|
|
196
|
+
];
|
|
197
|
+
if (target.kind === "fitBH") return [pdfName("FitBH"), n(target.topPt)];
|
|
198
|
+
if (target.kind === "fitBV") return [pdfName("FitBV"), n(target.leftPt)];
|
|
199
|
+
return [pdfName(target.kind === "fitB" ? "FitB" : "Fit")];
|
|
200
|
+
}
|
|
201
|
+
function buildInternalLinkAnnotDict(link, doc, pageAllocs) {
|
|
202
|
+
const destination = doc.destinations?.find((d) => d.name === link.destination);
|
|
203
|
+
if (destination === void 0) throw new Error(`internal link names destination "${link.destination}", which the document's destinations table does not carry -- this is a caller-invariant violation`);
|
|
204
|
+
const targetPage = pageAllocs[destination.pageIndex];
|
|
205
|
+
if (targetPage === void 0) throw new Error(`destination "${link.destination}" names page index ${destination.pageIndex}, which is beyond the document's own pages -- this is a caller-invariant violation`);
|
|
206
|
+
return pdfDict({
|
|
207
|
+
Type: pdfName("Annot"),
|
|
208
|
+
Subtype: pdfName("Link"),
|
|
209
|
+
Rect: pdfArray([
|
|
210
|
+
link.xPt,
|
|
211
|
+
link.yPt,
|
|
212
|
+
link.xPt + link.widthPt,
|
|
213
|
+
link.yPt + link.heightPt
|
|
214
|
+
].map((v) => pdfNum(v))),
|
|
215
|
+
Border: pdfArray([
|
|
216
|
+
0,
|
|
217
|
+
0,
|
|
218
|
+
0
|
|
219
|
+
].map((v) => pdfNum(v))),
|
|
220
|
+
Dest: pdfArray([pdfRef(targetPage.pageNum, 0), ...destinationViewArray(destination.target)])
|
|
221
|
+
});
|
|
222
|
+
}
|
|
180
223
|
function isLinkItem(item) {
|
|
181
224
|
return item.kind === "link";
|
|
182
225
|
}
|
|
226
|
+
function isInternalLinkItem(item) {
|
|
227
|
+
return item.kind === "internalLink";
|
|
228
|
+
}
|
|
183
229
|
const NOTES_ANNOTATION_HIDDEN_FLAG = 2;
|
|
184
230
|
function buildNotesAnnotDict(notes) {
|
|
185
231
|
return pdfDict({
|
|
@@ -435,7 +481,7 @@ function writePdf(doc, options = {}) {
|
|
|
435
481
|
num: contentsNum,
|
|
436
482
|
value: pdfStream(contentsDict, finalContentBytes)
|
|
437
483
|
});
|
|
438
|
-
const annots = page.items.filter(isLinkItem).map((link) => buildLinkAnnotDict(link));
|
|
484
|
+
const annots = [...page.items.filter(isLinkItem).map((link) => buildLinkAnnotDict(link)), ...page.items.filter(isInternalLinkItem).map((link) => buildInternalLinkAnnotDict(link, doc, pageAllocs))];
|
|
439
485
|
if (page.notes !== void 0 && page.notes.length > 0) annots.push(buildNotesAnnotDict(page.notes));
|
|
440
486
|
const pageEntries = /* @__PURE__ */ new Map([
|
|
441
487
|
["Type", pdfName("Page")],
|
package/dist/xmp.cjs
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/xmp.ts
|
|
3
|
+
function readXmpMetadata(packet) {
|
|
4
|
+
return {
|
|
5
|
+
...field(xmpValue(packet, "dc:title"), "title"),
|
|
6
|
+
...field(xmpValue(packet, "dc:creator"), "author"),
|
|
7
|
+
...field(xmpValue(packet, "dc:description"), "subject"),
|
|
8
|
+
...field(xmpValue(packet, "xmp:CreatorTool"), "creator"),
|
|
9
|
+
...field(xmpValue(packet, "pdf:Producer"), "producer"),
|
|
10
|
+
...field(xmpValue(packet, "xmp:CreateDate"), "createdIso"),
|
|
11
|
+
...field(xmpValue(packet, "xmp:ModifyDate"), "modifiedIso"),
|
|
12
|
+
...keywordsOf(packet)
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function xmpValue(packet, element) {
|
|
16
|
+
const match = new RegExp(`<${element}(?:\\s[^>]*)?>([\\s\\S]*?)</${element}>`).exec(packet);
|
|
17
|
+
if (match === null) return;
|
|
18
|
+
const inner = match[1] ?? "";
|
|
19
|
+
const items = listItems(inner);
|
|
20
|
+
if (items.length > 0) return items;
|
|
21
|
+
const text = inner.trim();
|
|
22
|
+
return text.length > 0 ? text : void 0;
|
|
23
|
+
}
|
|
24
|
+
function listItems(inner) {
|
|
25
|
+
const items = [];
|
|
26
|
+
const pattern = /<rdf:li(?:\s[^>]*)?>([\s\S]*?)<\/rdf:li>/g;
|
|
27
|
+
let match;
|
|
28
|
+
while ((match = pattern.exec(inner)) !== null) {
|
|
29
|
+
const text = (match[1] ?? "").trim();
|
|
30
|
+
if (text.length > 0) items.push(text);
|
|
31
|
+
}
|
|
32
|
+
return items;
|
|
33
|
+
}
|
|
34
|
+
function field(value, key) {
|
|
35
|
+
if (typeof value === "string") return { [key]: value };
|
|
36
|
+
if (Array.isArray(value) && value.length > 0) return { [key]: value.join(", ") };
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
function keywordsOf(packet) {
|
|
40
|
+
const match = (/* @__PURE__ */ new RegExp("<dc:subject(?:\\s[^>]*)?>([\\s\\S]*?)</dc:subject>")).exec(packet);
|
|
41
|
+
if (match === null) return {};
|
|
42
|
+
const items = listItems(match[1] ?? "");
|
|
43
|
+
return items.length > 0 ? { keywords: items } : {};
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
exports.readXmpMetadata = readXmpMetadata;
|
package/dist/xmp.d.cts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/xmp.d.ts
|
|
2
|
+
interface XmpMetadata {
|
|
3
|
+
readonly title?: string;
|
|
4
|
+
readonly author?: string;
|
|
5
|
+
readonly subject?: string;
|
|
6
|
+
readonly keywords?: string[];
|
|
7
|
+
readonly creator?: string;
|
|
8
|
+
readonly producer?: string;
|
|
9
|
+
readonly createdIso?: string;
|
|
10
|
+
readonly modifiedIso?: string;
|
|
11
|
+
}
|
|
12
|
+
declare function readXmpMetadata(packet: string): XmpMetadata;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { XmpMetadata, readXmpMetadata };
|
package/dist/xmp.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/xmp.d.ts
|
|
2
|
+
interface XmpMetadata {
|
|
3
|
+
readonly title?: string;
|
|
4
|
+
readonly author?: string;
|
|
5
|
+
readonly subject?: string;
|
|
6
|
+
readonly keywords?: string[];
|
|
7
|
+
readonly creator?: string;
|
|
8
|
+
readonly producer?: string;
|
|
9
|
+
readonly createdIso?: string;
|
|
10
|
+
readonly modifiedIso?: string;
|
|
11
|
+
}
|
|
12
|
+
declare function readXmpMetadata(packet: string): XmpMetadata;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { XmpMetadata, readXmpMetadata };
|
package/dist/xmp.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/xmp.ts
|
|
2
|
+
function readXmpMetadata(packet) {
|
|
3
|
+
return {
|
|
4
|
+
...field(xmpValue(packet, "dc:title"), "title"),
|
|
5
|
+
...field(xmpValue(packet, "dc:creator"), "author"),
|
|
6
|
+
...field(xmpValue(packet, "dc:description"), "subject"),
|
|
7
|
+
...field(xmpValue(packet, "xmp:CreatorTool"), "creator"),
|
|
8
|
+
...field(xmpValue(packet, "pdf:Producer"), "producer"),
|
|
9
|
+
...field(xmpValue(packet, "xmp:CreateDate"), "createdIso"),
|
|
10
|
+
...field(xmpValue(packet, "xmp:ModifyDate"), "modifiedIso"),
|
|
11
|
+
...keywordsOf(packet)
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function xmpValue(packet, element) {
|
|
15
|
+
const match = new RegExp(`<${element}(?:\\s[^>]*)?>([\\s\\S]*?)</${element}>`).exec(packet);
|
|
16
|
+
if (match === null) return;
|
|
17
|
+
const inner = match[1] ?? "";
|
|
18
|
+
const items = listItems(inner);
|
|
19
|
+
if (items.length > 0) return items;
|
|
20
|
+
const text = inner.trim();
|
|
21
|
+
return text.length > 0 ? text : void 0;
|
|
22
|
+
}
|
|
23
|
+
function listItems(inner) {
|
|
24
|
+
const items = [];
|
|
25
|
+
const pattern = /<rdf:li(?:\s[^>]*)?>([\s\S]*?)<\/rdf:li>/g;
|
|
26
|
+
let match;
|
|
27
|
+
while ((match = pattern.exec(inner)) !== null) {
|
|
28
|
+
const text = (match[1] ?? "").trim();
|
|
29
|
+
if (text.length > 0) items.push(text);
|
|
30
|
+
}
|
|
31
|
+
return items;
|
|
32
|
+
}
|
|
33
|
+
function field(value, key) {
|
|
34
|
+
if (typeof value === "string") return { [key]: value };
|
|
35
|
+
if (Array.isArray(value) && value.length > 0) return { [key]: value.join(", ") };
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
function keywordsOf(packet) {
|
|
39
|
+
const match = (/* @__PURE__ */ new RegExp("<dc:subject(?:\\s[^>]*)?>([\\s\\S]*?)</dc:subject>")).exec(packet);
|
|
40
|
+
if (match === null) return {};
|
|
41
|
+
const items = listItems(match[1] ?? "");
|
|
42
|
+
return items.length > 0 ? { keywords: items } : {};
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { readXmpMetadata };
|