@libpdf/core 0.0.1-beta.6 → 0.0.1-beta.7
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/dist/index.d.mts +171 -120
- package/dist/index.mjs +867 -785
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deflate, inflate } from "pako";
|
|
1
|
+
import pako, { deflate, inflate } from "pako";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { cbc, ecb } from "@noble/ciphers/aes.js";
|
|
4
4
|
import { randomBytes } from "@noble/ciphers/utils.js";
|
|
@@ -9,7 +9,7 @@ import * as pkijs from "pkijs";
|
|
|
9
9
|
import { base64 } from "@scure/base";
|
|
10
10
|
|
|
11
11
|
//#region package.json
|
|
12
|
-
var version = "0.0.1-beta.
|
|
12
|
+
var version = "0.0.1-beta.7";
|
|
13
13
|
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region src/objects/pdf-array.ts
|
|
@@ -906,7 +906,7 @@ var ASCIIHexFilter = class ASCIIHexFilter {
|
|
|
906
906
|
name = "ASCIIHexDecode";
|
|
907
907
|
static END_MARKER = 62;
|
|
908
908
|
static NIBBLE_MASK = 15;
|
|
909
|
-
|
|
909
|
+
decode(data, _params) {
|
|
910
910
|
const output = new ByteWriter();
|
|
911
911
|
let high = null;
|
|
912
912
|
for (const byte of data) {
|
|
@@ -923,7 +923,7 @@ var ASCIIHexFilter = class ASCIIHexFilter {
|
|
|
923
923
|
if (high !== null) output.writeByte(high << 4);
|
|
924
924
|
return output.toBytes();
|
|
925
925
|
}
|
|
926
|
-
|
|
926
|
+
encode(data, _params) {
|
|
927
927
|
const hexChars = "0123456789ABCDEF";
|
|
928
928
|
const result = new Uint8Array(data.length * 2 + 1);
|
|
929
929
|
let i = 0;
|
|
@@ -956,7 +956,7 @@ var ASCII85Filter = class ASCII85Filter {
|
|
|
956
956
|
static END_MARKER = 126;
|
|
957
957
|
static END_MARKER_FOLLOWING = 62;
|
|
958
958
|
static ZERO_SHORTCUT = 122;
|
|
959
|
-
|
|
959
|
+
decode(data, _params) {
|
|
960
960
|
const output = new ByteWriter();
|
|
961
961
|
let buffer = 0;
|
|
962
962
|
let count = 0;
|
|
@@ -994,7 +994,7 @@ var ASCII85Filter = class ASCII85Filter {
|
|
|
994
994
|
}
|
|
995
995
|
return output.toBytes();
|
|
996
996
|
}
|
|
997
|
-
|
|
997
|
+
encode(data, _params) {
|
|
998
998
|
const output = new ByteWriter();
|
|
999
999
|
let i = 0;
|
|
1000
1000
|
while (i < data.length) {
|
|
@@ -1051,7 +1051,7 @@ var ASCII85Filter = class ASCII85Filter {
|
|
|
1051
1051
|
*/
|
|
1052
1052
|
var CCITTFaxFilter = class {
|
|
1053
1053
|
name = "CCITTFaxDecode";
|
|
1054
|
-
|
|
1054
|
+
decode(data, params) {
|
|
1055
1055
|
const k = params?.getNumber("K")?.value ?? 0;
|
|
1056
1056
|
const columns = params?.getNumber("Columns")?.value ?? 1728;
|
|
1057
1057
|
const rows = params?.getNumber("Rows")?.value ?? 0;
|
|
@@ -1065,7 +1065,7 @@ var CCITTFaxFilter = class {
|
|
|
1065
1065
|
if (!blackIs1) for (let i = 0; i < result.length; i++) result[i] = ~result[i] & SINGLE_BYTE_MASK;
|
|
1066
1066
|
return result;
|
|
1067
1067
|
}
|
|
1068
|
-
|
|
1068
|
+
encode(_data, _params) {
|
|
1069
1069
|
throw new Error("CCITTFaxDecode: Encoding not implemented");
|
|
1070
1070
|
}
|
|
1071
1071
|
/**
|
|
@@ -1374,7 +1374,7 @@ var DCTFilter = class {
|
|
|
1374
1374
|
* - Decoded by canvas.drawImage()
|
|
1375
1375
|
* - Passed to an external JPEG library for pixel access
|
|
1376
1376
|
*/
|
|
1377
|
-
|
|
1377
|
+
decode(data, _params) {
|
|
1378
1378
|
if (data.length >= 2) {
|
|
1379
1379
|
if (data[0] !== 255 || data[1] !== 216) console.warn("DCTDecode: Data does not appear to be valid JPEG");
|
|
1380
1380
|
}
|
|
@@ -1385,7 +1385,7 @@ var DCTFilter = class {
|
|
|
1385
1385
|
*
|
|
1386
1386
|
* For actual JPEG encoding from raw pixels, use an external library.
|
|
1387
1387
|
*/
|
|
1388
|
-
|
|
1388
|
+
encode(data, _params) {
|
|
1389
1389
|
return data;
|
|
1390
1390
|
}
|
|
1391
1391
|
};
|
|
@@ -1572,15 +1572,15 @@ function paethPredictor$1(a, b, c) {
|
|
|
1572
1572
|
*/
|
|
1573
1573
|
var FlateFilter = class {
|
|
1574
1574
|
name = "FlateDecode";
|
|
1575
|
-
|
|
1576
|
-
const decompressed =
|
|
1575
|
+
decode(data, params) {
|
|
1576
|
+
const decompressed = pako.inflate(data);
|
|
1577
1577
|
if (params) {
|
|
1578
1578
|
if ((params.getNumber("Predictor")?.value ?? 1) > 1) return applyPredictor(decompressed, params);
|
|
1579
1579
|
}
|
|
1580
1580
|
return decompressed;
|
|
1581
1581
|
}
|
|
1582
|
-
|
|
1583
|
-
return
|
|
1582
|
+
encode(data, _params) {
|
|
1583
|
+
return pako.deflate(data);
|
|
1584
1584
|
}
|
|
1585
1585
|
};
|
|
1586
1586
|
|
|
@@ -1606,11 +1606,11 @@ var FlateFilter = class {
|
|
|
1606
1606
|
*/
|
|
1607
1607
|
var JBIG2Filter = class {
|
|
1608
1608
|
name = "JBIG2Decode";
|
|
1609
|
-
|
|
1609
|
+
decode(data, params) {
|
|
1610
1610
|
if (params?.get("JBIG2Globals")) throw new Error("JBIG2Decode: Decoding not implemented. This stream uses JBIG2 compression with global symbols. Consider using an external JBIG2 decoder library.");
|
|
1611
1611
|
throw new Error(`JBIG2Decode: Decoding not implemented. Stream contains ${data.length} bytes of JBIG2 data. Consider using an external JBIG2 decoder library (e.g., jbig2dec).`);
|
|
1612
1612
|
}
|
|
1613
|
-
|
|
1613
|
+
encode(_data, _params) {
|
|
1614
1614
|
throw new Error("JBIG2Decode: Encoding not implemented");
|
|
1615
1615
|
}
|
|
1616
1616
|
/**
|
|
@@ -1643,11 +1643,11 @@ var JBIG2Filter = class {
|
|
|
1643
1643
|
*/
|
|
1644
1644
|
var JPXFilter = class {
|
|
1645
1645
|
name = "JPXDecode";
|
|
1646
|
-
|
|
1646
|
+
decode(data, _params) {
|
|
1647
1647
|
const isValidJP2 = this.isJPEG2000(data);
|
|
1648
1648
|
throw new Error(`JPXDecode: Decoding not implemented. Stream contains ${data.length} bytes of ${isValidJP2 ? "valid" : "possible"} JPEG 2000 data. Consider using an external JPEG 2000 decoder library (e.g., OpenJPEG).`);
|
|
1649
1649
|
}
|
|
1650
|
-
|
|
1650
|
+
encode(_data, _params) {
|
|
1651
1651
|
throw new Error("JPXDecode: Encoding not implemented");
|
|
1652
1652
|
}
|
|
1653
1653
|
/**
|
|
@@ -1701,7 +1701,7 @@ var LZWFilter = class LZWFilter {
|
|
|
1701
1701
|
name = "LZWDecode";
|
|
1702
1702
|
static CLEAR_CODE = 256;
|
|
1703
1703
|
static EOD_CODE = 257;
|
|
1704
|
-
|
|
1704
|
+
decode(data, params) {
|
|
1705
1705
|
const earlyChange = params?.getNumber("EarlyChange")?.value ?? 1;
|
|
1706
1706
|
const result = this.lzwDecode(data, earlyChange);
|
|
1707
1707
|
if (params) {
|
|
@@ -1709,7 +1709,7 @@ var LZWFilter = class LZWFilter {
|
|
|
1709
1709
|
}
|
|
1710
1710
|
return result;
|
|
1711
1711
|
}
|
|
1712
|
-
|
|
1712
|
+
encode(_data, _params) {
|
|
1713
1713
|
throw new Error("LZW encoding not implemented");
|
|
1714
1714
|
}
|
|
1715
1715
|
lzwDecode(data, earlyChange) {
|
|
@@ -1793,7 +1793,7 @@ var LZWFilter = class LZWFilter {
|
|
|
1793
1793
|
*/
|
|
1794
1794
|
var RunLengthFilter = class {
|
|
1795
1795
|
name = "RunLengthDecode";
|
|
1796
|
-
|
|
1796
|
+
decode(data, _params) {
|
|
1797
1797
|
const output = new ByteWriter();
|
|
1798
1798
|
let i = 0;
|
|
1799
1799
|
while (i < data.length) {
|
|
@@ -1810,7 +1810,7 @@ var RunLengthFilter = class {
|
|
|
1810
1810
|
}
|
|
1811
1811
|
return output.toBytes();
|
|
1812
1812
|
}
|
|
1813
|
-
|
|
1813
|
+
encode(data, _params) {
|
|
1814
1814
|
const output = new ByteWriter();
|
|
1815
1815
|
let i = 0;
|
|
1816
1816
|
while (i < data.length) {
|
|
@@ -1898,14 +1898,14 @@ var FilterPipeline = class FilterPipeline {
|
|
|
1898
1898
|
* @returns Decoded data
|
|
1899
1899
|
* @throws {Error} if a filter is not registered
|
|
1900
1900
|
*/
|
|
1901
|
-
static
|
|
1901
|
+
static decode(data, filters) {
|
|
1902
1902
|
const filterList = Array.isArray(filters) ? filters : [filters];
|
|
1903
1903
|
if (filterList.length === 0) return data;
|
|
1904
1904
|
let result = data;
|
|
1905
1905
|
for (const spec of filterList) {
|
|
1906
1906
|
const filter = FilterPipeline.filters.get(spec.name);
|
|
1907
1907
|
if (!filter) throw new Error(`Unknown filter: ${spec.name}`);
|
|
1908
|
-
result =
|
|
1908
|
+
result = filter.decode(result, spec.params);
|
|
1909
1909
|
}
|
|
1910
1910
|
return result;
|
|
1911
1911
|
}
|
|
@@ -1921,14 +1921,14 @@ var FilterPipeline = class FilterPipeline {
|
|
|
1921
1921
|
* @returns Encoded data
|
|
1922
1922
|
* @throws {Error} if a filter is not registered
|
|
1923
1923
|
*/
|
|
1924
|
-
static
|
|
1924
|
+
static encode(data, filters) {
|
|
1925
1925
|
const filterList = Array.isArray(filters) ? filters : [filters];
|
|
1926
1926
|
if (filterList.length === 0) return data;
|
|
1927
1927
|
let result = data;
|
|
1928
1928
|
for (const spec of filterList.toReversed()) {
|
|
1929
1929
|
const filter = FilterPipeline.filters.get(spec.name);
|
|
1930
1930
|
if (!filter) throw new Error(`Unknown filter: ${spec.name}`);
|
|
1931
|
-
result =
|
|
1931
|
+
result = filter.encode(result, spec.params);
|
|
1932
1932
|
}
|
|
1933
1933
|
return result;
|
|
1934
1934
|
}
|
|
@@ -2033,7 +2033,7 @@ var PdfStream = class PdfStream extends PdfDict {
|
|
|
2033
2033
|
* @returns Decoded data
|
|
2034
2034
|
* @throws {Error} if a filter fails or is unknown
|
|
2035
2035
|
*/
|
|
2036
|
-
|
|
2036
|
+
getDecodedData() {
|
|
2037
2037
|
const filterEntry = this.get("Filter");
|
|
2038
2038
|
if (!filterEntry) return this._data;
|
|
2039
2039
|
const filterSpecs = this.buildFilterSpecs(filterEntry);
|
|
@@ -2055,7 +2055,7 @@ var PdfStream = class PdfStream extends PdfDict {
|
|
|
2055
2055
|
*
|
|
2056
2056
|
* @returns Encoded data (compressed if filters are specified)
|
|
2057
2057
|
*/
|
|
2058
|
-
|
|
2058
|
+
getEncodedData() {
|
|
2059
2059
|
const filterEntry = this.get("Filter");
|
|
2060
2060
|
if (!filterEntry) return this._data;
|
|
2061
2061
|
const filterSpecs = this.buildFilterSpecs(filterEntry);
|
|
@@ -2154,11 +2154,11 @@ var ObjectCopier = class {
|
|
|
2154
2154
|
* @returns Reference to the copied page in destination document
|
|
2155
2155
|
*/
|
|
2156
2156
|
async copyPage(srcPageRef) {
|
|
2157
|
-
const srcPage =
|
|
2158
|
-
if (!(srcPage instanceof PdfDict)) throw new Error(`Page object not found or not a dictionary: ${srcPageRef}`);
|
|
2157
|
+
const srcPage = this.source.getObject(srcPageRef);
|
|
2158
|
+
if (!(srcPage instanceof PdfDict)) throw new Error(`Page object not found or not a dictionary: ${srcPageRef.objectNumber} ${srcPageRef.generation} R`);
|
|
2159
2159
|
const cloned = srcPage.clone();
|
|
2160
2160
|
for (const key$1 of INHERITABLE_PAGE_ATTRS) if (!cloned.has(key$1)) {
|
|
2161
|
-
const inherited =
|
|
2161
|
+
const inherited = this.getInheritedAttribute(srcPage, key$1);
|
|
2162
2162
|
if (inherited) {
|
|
2163
2163
|
const copied = await this.copyObject(inherited);
|
|
2164
2164
|
cloned.set(key$1, copied);
|
|
@@ -2176,10 +2176,10 @@ var ObjectCopier = class {
|
|
|
2176
2176
|
* Deep copy any PDF object, remapping references to destination.
|
|
2177
2177
|
*/
|
|
2178
2178
|
async copyObject(obj) {
|
|
2179
|
-
if (obj instanceof PdfRef) return this.copyRef(obj);
|
|
2180
|
-
if (obj instanceof PdfStream) return this.copyStream(obj);
|
|
2181
|
-
if (obj instanceof PdfDict) return this.copyDict(obj);
|
|
2182
|
-
if (obj instanceof PdfArray) return this.copyArray(obj);
|
|
2179
|
+
if (obj instanceof PdfRef) return await this.copyRef(obj);
|
|
2180
|
+
if (obj instanceof PdfStream) return await this.copyStream(obj);
|
|
2181
|
+
if (obj instanceof PdfDict) return await this.copyDict(obj);
|
|
2182
|
+
if (obj instanceof PdfArray) return await this.copyArray(obj);
|
|
2183
2183
|
return obj;
|
|
2184
2184
|
}
|
|
2185
2185
|
/**
|
|
@@ -2192,7 +2192,7 @@ var ObjectCopier = class {
|
|
|
2192
2192
|
const key$1 = `${ref.objectNumber}:${ref.generation}`;
|
|
2193
2193
|
const existing = this.refMap.get(key$1);
|
|
2194
2194
|
if (existing) return existing;
|
|
2195
|
-
const srcObj =
|
|
2195
|
+
const srcObj = this.source.getObject(ref);
|
|
2196
2196
|
if (srcObj === null) {
|
|
2197
2197
|
const nullRef = this.dest.register(new PdfDict());
|
|
2198
2198
|
this.refMap.set(key$1, nullRef);
|
|
@@ -2231,10 +2231,10 @@ var ObjectCopier = class {
|
|
|
2231
2231
|
let streamData;
|
|
2232
2232
|
if (!sourceWasEncrypted) streamData = srcStream.data;
|
|
2233
2233
|
else try {
|
|
2234
|
-
const decodedData =
|
|
2234
|
+
const decodedData = srcStream.getDecodedData();
|
|
2235
2235
|
if (srcStream.get("Filter")) try {
|
|
2236
2236
|
const filterSpecs = this.buildFilterSpecs(srcStream);
|
|
2237
|
-
streamData =
|
|
2237
|
+
streamData = FilterPipeline.encode(decodedData, filterSpecs);
|
|
2238
2238
|
clonedDict.set("Length", PdfNumber.of(streamData.length));
|
|
2239
2239
|
} catch (error) {
|
|
2240
2240
|
console.warn(`Could not re-encode stream ${key$1}, will use uncompressed data`);
|
|
@@ -2303,10 +2303,10 @@ var ObjectCopier = class {
|
|
|
2303
2303
|
await this.copyDictValues(clonedDict);
|
|
2304
2304
|
if (!sourceWasEncrypted) return new PdfStream(clonedDict, stream.data);
|
|
2305
2305
|
try {
|
|
2306
|
-
const decodedData =
|
|
2306
|
+
const decodedData = stream.getDecodedData();
|
|
2307
2307
|
if (stream.get("Filter")) try {
|
|
2308
2308
|
const filterSpecs = this.buildFilterSpecs(stream);
|
|
2309
|
-
const encodedData =
|
|
2309
|
+
const encodedData = FilterPipeline.encode(decodedData, filterSpecs);
|
|
2310
2310
|
clonedDict.set("Length", PdfNumber.of(encodedData.length));
|
|
2311
2311
|
return new PdfStream(clonedDict, encodedData);
|
|
2312
2312
|
} catch (error) {
|
|
@@ -2351,14 +2351,14 @@ var ObjectCopier = class {
|
|
|
2351
2351
|
/**
|
|
2352
2352
|
* Walk up the page tree to find an inherited attribute.
|
|
2353
2353
|
*/
|
|
2354
|
-
|
|
2354
|
+
getInheritedAttribute(page, key$1) {
|
|
2355
2355
|
let current = page;
|
|
2356
2356
|
while (current) {
|
|
2357
2357
|
const value = current.get(key$1);
|
|
2358
2358
|
if (value) return value;
|
|
2359
2359
|
const parentRef = current.getRef("Parent");
|
|
2360
2360
|
if (!parentRef) break;
|
|
2361
|
-
const parent =
|
|
2361
|
+
const parent = this.source.getObject(parentRef);
|
|
2362
2362
|
current = parent instanceof PdfDict ? parent : null;
|
|
2363
2363
|
}
|
|
2364
2364
|
return null;
|
|
@@ -2486,11 +2486,11 @@ var ObjectRegistry = class {
|
|
|
2486
2486
|
* @param ref - The reference to resolve
|
|
2487
2487
|
* @returns The object, or null if not found
|
|
2488
2488
|
*/
|
|
2489
|
-
|
|
2489
|
+
resolve(ref) {
|
|
2490
2490
|
const existing = this.getObject(ref);
|
|
2491
2491
|
if (existing !== null) return existing;
|
|
2492
2492
|
if (this.resolver) {
|
|
2493
|
-
const obj =
|
|
2493
|
+
const obj = this.resolver(ref);
|
|
2494
2494
|
if (obj !== null) this.addLoaded(ref, obj);
|
|
2495
2495
|
return obj;
|
|
2496
2496
|
}
|
|
@@ -3597,7 +3597,7 @@ function refKey(ref) {
|
|
|
3597
3597
|
/**
|
|
3598
3598
|
* Parse the default configuration from OCProperties.D
|
|
3599
3599
|
*/
|
|
3600
|
-
|
|
3600
|
+
function parseDefaultConfig(dDict, resolve) {
|
|
3601
3601
|
const result = {
|
|
3602
3602
|
baseState: "ON",
|
|
3603
3603
|
onRefs: /* @__PURE__ */ new Set(),
|
|
@@ -3606,10 +3606,9 @@ async function parseDefaultConfig(dDict, resolve) {
|
|
|
3606
3606
|
};
|
|
3607
3607
|
if (!dDict) return result;
|
|
3608
3608
|
let dict = null;
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
} else if (dDict instanceof PdfDict) dict = dDict;
|
|
3609
|
+
let resolved = dDict;
|
|
3610
|
+
if (resolved instanceof PdfRef) resolved = resolve(resolved) ?? void 0;
|
|
3611
|
+
if (resolved instanceof PdfDict) dict = resolved;
|
|
3613
3612
|
if (!dict) return result;
|
|
3614
3613
|
const baseState = dict.get("BaseState");
|
|
3615
3614
|
if (baseState instanceof PdfName) {
|
|
@@ -3636,19 +3635,19 @@ async function parseDefaultConfig(dDict, resolve) {
|
|
|
3636
3635
|
* Performs a thorough check that verifies OCProperties exists and
|
|
3637
3636
|
* contains at least one valid OCG entry.
|
|
3638
3637
|
*/
|
|
3639
|
-
|
|
3638
|
+
function hasLayers(ctx) {
|
|
3640
3639
|
const catalog = ctx.catalog.getDict();
|
|
3641
3640
|
if (!catalog) return false;
|
|
3642
3641
|
let ocProperties = catalog.get("OCProperties");
|
|
3643
3642
|
if (!ocProperties) return false;
|
|
3644
3643
|
let ocPropsDict = null;
|
|
3645
|
-
if (ocProperties instanceof PdfRef) ocProperties =
|
|
3644
|
+
if (ocProperties instanceof PdfRef) ocProperties = ctx.resolve(ocProperties) ?? void 0;
|
|
3646
3645
|
if (ocProperties instanceof PdfDict) ocPropsDict = ocProperties;
|
|
3647
3646
|
if (!ocPropsDict) return false;
|
|
3648
3647
|
let ocgs = ocPropsDict.get("OCGs");
|
|
3649
3648
|
if (!ocgs) return false;
|
|
3650
3649
|
let ocgsArray = null;
|
|
3651
|
-
if (ocgs instanceof PdfRef) ocgs =
|
|
3650
|
+
if (ocgs instanceof PdfRef) ocgs = ctx.resolve(ocgs) ?? void 0;
|
|
3652
3651
|
if (ocgs instanceof PdfArray) ocgsArray = ocgs;
|
|
3653
3652
|
if (!ocgsArray || ocgsArray.length === 0) return false;
|
|
3654
3653
|
return true;
|
|
@@ -3659,32 +3658,32 @@ async function hasLayers(ctx) {
|
|
|
3659
3658
|
* Returns layer metadata including name, visibility state,
|
|
3660
3659
|
* intent, and locked status based on the default configuration.
|
|
3661
3660
|
*/
|
|
3662
|
-
|
|
3661
|
+
function getLayers(ctx) {
|
|
3663
3662
|
const catalog = ctx.catalog.getDict();
|
|
3664
3663
|
if (!catalog) return [];
|
|
3665
3664
|
let ocProperties = catalog.get("OCProperties");
|
|
3666
3665
|
if (!ocProperties) return [];
|
|
3667
3666
|
let ocPropsDict = null;
|
|
3668
|
-
if (ocProperties instanceof PdfRef) ocProperties =
|
|
3667
|
+
if (ocProperties instanceof PdfRef) ocProperties = ctx.resolve(ocProperties) ?? void 0;
|
|
3669
3668
|
if (ocProperties instanceof PdfDict) ocPropsDict = ocProperties;
|
|
3670
3669
|
if (!ocPropsDict) return [];
|
|
3671
3670
|
let ocgs = ocPropsDict.get("OCGs");
|
|
3672
3671
|
if (!ocgs) return [];
|
|
3673
3672
|
let ocgsArray = null;
|
|
3674
|
-
if (ocgs instanceof PdfRef) ocgs =
|
|
3673
|
+
if (ocgs instanceof PdfRef) ocgs = ctx.resolve(ocgs) ?? void 0;
|
|
3675
3674
|
if (ocgs instanceof PdfArray) ocgsArray = ocgs;
|
|
3676
3675
|
if (!ocgsArray) return [];
|
|
3677
|
-
const defaultConfig =
|
|
3676
|
+
const defaultConfig = parseDefaultConfig(ocPropsDict.get("D"), (ref) => ctx.resolve(ref));
|
|
3678
3677
|
const layers = [];
|
|
3679
3678
|
for (const item of ocgsArray) {
|
|
3680
3679
|
if (!(item instanceof PdfRef)) continue;
|
|
3681
|
-
const ocg =
|
|
3680
|
+
const ocg = ctx.resolve(item);
|
|
3682
3681
|
if (!(ocg instanceof PdfDict)) continue;
|
|
3683
3682
|
const nameObj = ocg.get("Name");
|
|
3684
3683
|
let name = "Unnamed";
|
|
3685
3684
|
if (nameObj instanceof PdfString) name = nameObj.asString();
|
|
3686
3685
|
else if (nameObj instanceof PdfName) name = nameObj.value;
|
|
3687
|
-
else if (nameObj) name =
|
|
3686
|
+
else if (nameObj) name = `[${nameObj.type}]`;
|
|
3688
3687
|
const intentObj = ocg.get("Intent");
|
|
3689
3688
|
let intent;
|
|
3690
3689
|
if (intentObj instanceof PdfName) intent = intentObj.value;
|
|
@@ -3715,7 +3714,7 @@ async function getLayers(ctx) {
|
|
|
3715
3714
|
* content unconditionally visible and removes the layer toggle UI from
|
|
3716
3715
|
* PDF viewers. No content is deleted - layers that were OFF become visible.
|
|
3717
3716
|
*/
|
|
3718
|
-
|
|
3717
|
+
function flattenLayers(ctx) {
|
|
3719
3718
|
const catalog = ctx.catalog.getDict();
|
|
3720
3719
|
if (!catalog) return {
|
|
3721
3720
|
flattened: false,
|
|
@@ -3725,7 +3724,7 @@ async function flattenLayers(ctx) {
|
|
|
3725
3724
|
flattened: false,
|
|
3726
3725
|
layerCount: 0
|
|
3727
3726
|
};
|
|
3728
|
-
const layerCount =
|
|
3727
|
+
const layerCount = getLayers(ctx).length;
|
|
3729
3728
|
catalog.delete("OCProperties");
|
|
3730
3729
|
return {
|
|
3731
3730
|
flattened: true,
|
|
@@ -6271,9 +6270,9 @@ var ObjectStreamParser = class {
|
|
|
6271
6270
|
* Decompress and parse the stream index.
|
|
6272
6271
|
* Called automatically by getObject/getAllObjects if needed.
|
|
6273
6272
|
*/
|
|
6274
|
-
|
|
6273
|
+
parse() {
|
|
6275
6274
|
if (this.index !== null) return;
|
|
6276
|
-
this.decodedData =
|
|
6275
|
+
this.decodedData = this.stream.getDecodedData();
|
|
6277
6276
|
this.index = this.parseIndex();
|
|
6278
6277
|
}
|
|
6279
6278
|
/**
|
|
@@ -6302,8 +6301,8 @@ var ObjectStreamParser = class {
|
|
|
6302
6301
|
* @param index - 0-based index from XRef entry's indexInStream
|
|
6303
6302
|
* @returns The parsed object, or null if index is out of range
|
|
6304
6303
|
*/
|
|
6305
|
-
|
|
6306
|
-
|
|
6304
|
+
getObject(index) {
|
|
6305
|
+
this.parse();
|
|
6307
6306
|
if (this.index === null) throw new ObjectParseError("Index not parsed");
|
|
6308
6307
|
if (index < 0 || index >= this.index.length) return null;
|
|
6309
6308
|
const entry = this.index[index];
|
|
@@ -6317,12 +6316,12 @@ var ObjectStreamParser = class {
|
|
|
6317
6316
|
*
|
|
6318
6317
|
* @returns Map of object number → parsed object
|
|
6319
6318
|
*/
|
|
6320
|
-
|
|
6321
|
-
|
|
6319
|
+
getAllObjects() {
|
|
6320
|
+
this.parse();
|
|
6322
6321
|
if (this.index === null) throw new ObjectParseError("Index not parsed");
|
|
6323
6322
|
const result = /* @__PURE__ */ new Map();
|
|
6324
6323
|
for (let i = 0; i < this.index.length; i++) {
|
|
6325
|
-
const obj =
|
|
6324
|
+
const obj = this.getObject(i);
|
|
6326
6325
|
if (obj !== null) result.set(this.index[i].objNum, obj);
|
|
6327
6326
|
}
|
|
6328
6327
|
return result;
|
|
@@ -6408,7 +6407,7 @@ var BruteForceParser = class {
|
|
|
6408
6407
|
* Scan file and build recovered xref.
|
|
6409
6408
|
* Returns null if no objects found or no valid root.
|
|
6410
6409
|
*/
|
|
6411
|
-
|
|
6410
|
+
recover() {
|
|
6412
6411
|
const entries = this.scanForObjects();
|
|
6413
6412
|
if (entries.length === 0) return null;
|
|
6414
6413
|
const xref = new RecoveredXRef();
|
|
@@ -6417,7 +6416,7 @@ var BruteForceParser = class {
|
|
|
6417
6416
|
xref.set(entry.objNum, entry.genNum, entry.offset);
|
|
6418
6417
|
maxObjNum = Math.max(maxObjNum, entry.objNum);
|
|
6419
6418
|
}
|
|
6420
|
-
const compressedEntries =
|
|
6419
|
+
const compressedEntries = this.extractFromObjectStreams(entries);
|
|
6421
6420
|
for (const entry of compressedEntries) {
|
|
6422
6421
|
xref.setCompressed(entry.objNum, entry.streamObjNum, entry.indexInStream);
|
|
6423
6422
|
maxObjNum = Math.max(maxObjNum, entry.objNum);
|
|
@@ -6594,8 +6593,8 @@ var BruteForceParser = class {
|
|
|
6594
6593
|
parseFullObjectAt(offset, objNum, genNum) {
|
|
6595
6594
|
try {
|
|
6596
6595
|
const result = new IndirectObjectParser(this.scanner).parseObjectAt(offset);
|
|
6597
|
-
if (result.value
|
|
6598
|
-
return
|
|
6596
|
+
if (result.value instanceof PdfStream) return result.value;
|
|
6597
|
+
return null;
|
|
6599
6598
|
} catch (error) {
|
|
6600
6599
|
const message = error instanceof Error ? error.message : String(error);
|
|
6601
6600
|
this.warnings.push(`Failed to parse object ${objNum} ${genNum} as stream: ${message}`);
|
|
@@ -6606,18 +6605,18 @@ var BruteForceParser = class {
|
|
|
6606
6605
|
* Find object streams among the scanned entries and extract their contents.
|
|
6607
6606
|
* This is crucial for PDFs where Catalog/Pages are stored inside object streams.
|
|
6608
6607
|
*/
|
|
6609
|
-
|
|
6608
|
+
extractFromObjectStreams(entries) {
|
|
6610
6609
|
const compressed = [];
|
|
6611
6610
|
for (const entry of entries) try {
|
|
6612
6611
|
const stream = this.parseFullObjectAt(entry.offset, entry.objNum, entry.genNum);
|
|
6613
6612
|
if (stream === null) continue;
|
|
6614
6613
|
if (stream.getName("Type")?.value !== "ObjStm") continue;
|
|
6615
6614
|
const objectStreamParser = new ObjectStreamParser(stream);
|
|
6616
|
-
|
|
6615
|
+
objectStreamParser.parse();
|
|
6617
6616
|
const count = objectStreamParser.objectCount;
|
|
6618
6617
|
for (let i = 0; i < count; i++) try {
|
|
6619
6618
|
const objNum = objectStreamParser.getObjectNumber(i);
|
|
6620
|
-
const obj =
|
|
6619
|
+
const obj = objectStreamParser.getObject(i);
|
|
6621
6620
|
if (objNum === null) continue;
|
|
6622
6621
|
compressed.push({
|
|
6623
6622
|
objNum,
|
|
@@ -6672,7 +6671,7 @@ var XRefParser = class {
|
|
|
6672
6671
|
* Parse xref at given byte offset.
|
|
6673
6672
|
* Auto-detects table vs stream format.
|
|
6674
6673
|
*/
|
|
6675
|
-
|
|
6674
|
+
parseAt(offset) {
|
|
6676
6675
|
this.scanner.moveTo(offset);
|
|
6677
6676
|
const firstByte = this.scanner.peek();
|
|
6678
6677
|
if (firstByte === 120) return this.parseTable();
|
|
@@ -6722,7 +6721,7 @@ var XRefParser = class {
|
|
|
6722
6721
|
* - /W [w1 w2 w3] - byte widths for type, offset, generation fields
|
|
6723
6722
|
* - /Index [first count ...] - object number ranges (optional, defaults to [0 Size])
|
|
6724
6723
|
*/
|
|
6725
|
-
|
|
6724
|
+
parseStream() {
|
|
6726
6725
|
const indirectObj = new IndirectObjectParser(this.scanner).parseObject();
|
|
6727
6726
|
if (!(indirectObj.value instanceof PdfStream)) throw new XRefParseError("Expected XRef stream object");
|
|
6728
6727
|
const stream = indirectObj.value;
|
|
@@ -6758,7 +6757,7 @@ var XRefParser = class {
|
|
|
6758
6757
|
first: 0,
|
|
6759
6758
|
count: size
|
|
6760
6759
|
});
|
|
6761
|
-
const decodedData =
|
|
6760
|
+
const decodedData = stream.getDecodedData();
|
|
6762
6761
|
const entries = /* @__PURE__ */ new Map();
|
|
6763
6762
|
let dataOffset = 0;
|
|
6764
6763
|
for (const range of ranges) for (let i = 0; i < range.count; i++) {
|
|
@@ -7009,9 +7008,9 @@ var DocumentParser = class {
|
|
|
7009
7008
|
/**
|
|
7010
7009
|
* Parse the PDF document.
|
|
7011
7010
|
*/
|
|
7012
|
-
|
|
7011
|
+
parse() {
|
|
7013
7012
|
try {
|
|
7014
|
-
return
|
|
7013
|
+
return this.parseNormal();
|
|
7015
7014
|
} catch (error) {
|
|
7016
7015
|
if (this.options.lenient && error instanceof RecoverableParseError) {
|
|
7017
7016
|
this.warnings.push(`Normal parsing failed: ${error.message}`);
|
|
@@ -7023,24 +7022,24 @@ var DocumentParser = class {
|
|
|
7023
7022
|
/**
|
|
7024
7023
|
* Normal parsing path.
|
|
7025
7024
|
*/
|
|
7026
|
-
|
|
7025
|
+
parseNormal() {
|
|
7027
7026
|
const version$1 = this.parseHeader();
|
|
7028
7027
|
const xrefParser = new XRefParser(this.scanner);
|
|
7029
7028
|
const startXRef = xrefParser.findStartXRef();
|
|
7030
|
-
const { xref, trailer } =
|
|
7029
|
+
const { xref, trailer } = this.parseXRefChain(xrefParser, startXRef);
|
|
7031
7030
|
return this.buildDocument(version$1, xref, trailer, false);
|
|
7032
7031
|
}
|
|
7033
7032
|
/**
|
|
7034
7033
|
* Recovery parsing using brute-force when normal parsing fails.
|
|
7035
7034
|
*/
|
|
7036
|
-
|
|
7035
|
+
parseWithRecovery() {
|
|
7037
7036
|
let version$1 = DEFAULT_VERSION;
|
|
7038
7037
|
try {
|
|
7039
7038
|
version$1 = this.parseHeader();
|
|
7040
7039
|
} catch {
|
|
7041
7040
|
this.warnings.push("Could not parse header, using default version");
|
|
7042
7041
|
}
|
|
7043
|
-
const result =
|
|
7042
|
+
const result = new BruteForceParser(this.scanner).recover();
|
|
7044
7043
|
if (result === null) throw new UnrecoverableParseError("Could not recover PDF structure: no objects found");
|
|
7045
7044
|
this.warnings.push(...result.warnings);
|
|
7046
7045
|
const xref = /* @__PURE__ */ new Map();
|
|
@@ -7108,7 +7107,7 @@ var DocumentParser = class {
|
|
|
7108
7107
|
/**
|
|
7109
7108
|
* Parse the XRef chain, following /Prev links for incremental updates.
|
|
7110
7109
|
*/
|
|
7111
|
-
|
|
7110
|
+
parseXRefChain(xrefParser, startOffset) {
|
|
7112
7111
|
const combinedXRef = /* @__PURE__ */ new Map();
|
|
7113
7112
|
let firstTrailer = null;
|
|
7114
7113
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -7122,7 +7121,7 @@ var DocumentParser = class {
|
|
|
7122
7121
|
}
|
|
7123
7122
|
visited.add(offset);
|
|
7124
7123
|
try {
|
|
7125
|
-
const xrefData =
|
|
7124
|
+
const xrefData = xrefParser.parseAt(offset);
|
|
7126
7125
|
for (const [objNum, entry] of xrefData.entries) if (!combinedXRef.has(objNum)) combinedXRef.set(objNum, entry);
|
|
7127
7126
|
if (!firstTrailer) firstTrailer = xrefData.trailer;
|
|
7128
7127
|
if (xrefData.prev !== void 0) queue.push(xrefData.prev);
|
|
@@ -7223,7 +7222,7 @@ var DocumentParser = class {
|
|
|
7223
7222
|
}
|
|
7224
7223
|
return obj;
|
|
7225
7224
|
};
|
|
7226
|
-
const getObject =
|
|
7225
|
+
const getObject = (ref) => {
|
|
7227
7226
|
const key$1 = `${ref.objectNumber} ${ref.generation}`;
|
|
7228
7227
|
if (cache.has(key$1)) return cache.get(key$1);
|
|
7229
7228
|
const entry = xref.get(ref.objectNumber);
|
|
@@ -7241,25 +7240,25 @@ var DocumentParser = class {
|
|
|
7241
7240
|
case "compressed": {
|
|
7242
7241
|
let streamParser = objectStreamCache.get(entry.streamObjNum);
|
|
7243
7242
|
if (!streamParser) {
|
|
7244
|
-
const streamObj =
|
|
7245
|
-
if (!streamObj || streamObj
|
|
7243
|
+
const streamObj = getObject(PdfRef.of(entry.streamObjNum, 0));
|
|
7244
|
+
if (!streamObj || !(streamObj instanceof PdfStream)) {
|
|
7246
7245
|
this.warnings.push(`Object stream ${entry.streamObjNum} not found or invalid`);
|
|
7247
7246
|
return null;
|
|
7248
7247
|
}
|
|
7249
7248
|
streamParser = new ObjectStreamParser(streamObj);
|
|
7250
7249
|
objectStreamCache.set(entry.streamObjNum, streamParser);
|
|
7251
7250
|
}
|
|
7252
|
-
obj =
|
|
7251
|
+
obj = streamParser.getObject(entry.indexInStream);
|
|
7253
7252
|
break;
|
|
7254
7253
|
}
|
|
7255
7254
|
}
|
|
7256
7255
|
if (obj !== null) cache.set(key$1, obj);
|
|
7257
7256
|
return obj;
|
|
7258
7257
|
};
|
|
7259
|
-
const getCatalog =
|
|
7258
|
+
const getCatalog = () => {
|
|
7260
7259
|
const rootRef = trailer.getRef("Root");
|
|
7261
7260
|
if (!rootRef) return null;
|
|
7262
|
-
const root =
|
|
7261
|
+
const root = getObject(rootRef);
|
|
7263
7262
|
if (!root || root.type !== "dict" && root.type !== "stream") return null;
|
|
7264
7263
|
return root;
|
|
7265
7264
|
};
|
|
@@ -7267,10 +7266,10 @@ var DocumentParser = class {
|
|
|
7267
7266
|
* Walk the page tree and collect all page references.
|
|
7268
7267
|
* Handles circular references and missing objects gracefully.
|
|
7269
7268
|
*/
|
|
7270
|
-
const getPages =
|
|
7269
|
+
const getPages = () => {
|
|
7271
7270
|
const pages = [];
|
|
7272
7271
|
const visited = /* @__PURE__ */ new Set();
|
|
7273
|
-
const walkNode =
|
|
7272
|
+
const walkNode = (nodeOrRef, currentRef) => {
|
|
7274
7273
|
if (nodeOrRef instanceof PdfRef) {
|
|
7275
7274
|
const key$1 = `${nodeOrRef.objectNumber} ${nodeOrRef.generation}`;
|
|
7276
7275
|
if (visited.has(key$1)) {
|
|
@@ -7278,7 +7277,7 @@ var DocumentParser = class {
|
|
|
7278
7277
|
return;
|
|
7279
7278
|
}
|
|
7280
7279
|
visited.add(key$1);
|
|
7281
|
-
|
|
7280
|
+
walkNode(getObject(nodeOrRef), nodeOrRef);
|
|
7282
7281
|
return;
|
|
7283
7282
|
}
|
|
7284
7283
|
if (!(nodeOrRef instanceof PdfDict)) return;
|
|
@@ -7289,19 +7288,19 @@ var DocumentParser = class {
|
|
|
7289
7288
|
const kids = nodeOrRef.getArray("Kids");
|
|
7290
7289
|
if (kids) for (let i = 0; i < kids.length; i++) {
|
|
7291
7290
|
const kid = kids.at(i);
|
|
7292
|
-
if (kid instanceof PdfRef)
|
|
7293
|
-
else if (kid instanceof PdfDict)
|
|
7291
|
+
if (kid instanceof PdfRef) walkNode(kid);
|
|
7292
|
+
else if (kid instanceof PdfDict) walkNode(kid);
|
|
7294
7293
|
}
|
|
7295
7294
|
}
|
|
7296
7295
|
};
|
|
7297
|
-
const catalog =
|
|
7296
|
+
const catalog = getCatalog();
|
|
7298
7297
|
if (!catalog) return pages;
|
|
7299
7298
|
const pagesRef = catalog.getRef("Pages");
|
|
7300
|
-
if (pagesRef)
|
|
7299
|
+
if (pagesRef) walkNode(pagesRef);
|
|
7301
7300
|
return pages;
|
|
7302
7301
|
};
|
|
7303
|
-
const getPageCount =
|
|
7304
|
-
return
|
|
7302
|
+
const getPageCount = () => {
|
|
7303
|
+
return getPages().length;
|
|
7305
7304
|
};
|
|
7306
7305
|
const authenticate = (password) => {
|
|
7307
7306
|
if (!securityHandler) return false;
|
|
@@ -7695,12 +7694,12 @@ function writeIndirectObject(writer, ref, obj) {
|
|
|
7695
7694
|
* Streams that already have filters are returned unchanged - this includes
|
|
7696
7695
|
* image formats (DCTDecode, JPXDecode, etc.) that are already compressed.
|
|
7697
7696
|
*/
|
|
7698
|
-
|
|
7697
|
+
function prepareObjectForWrite(obj, compress) {
|
|
7699
7698
|
if (!(obj instanceof PdfStream)) return obj;
|
|
7700
7699
|
if (obj.has("Filter")) return obj;
|
|
7701
7700
|
if (!compress) return obj;
|
|
7702
7701
|
if (obj.data.length === 0) return obj;
|
|
7703
|
-
const compressed =
|
|
7702
|
+
const compressed = FilterPipeline.encode(obj.data, { name: "FlateDecode" });
|
|
7704
7703
|
if (compressed.length >= obj.data.length) return obj;
|
|
7705
7704
|
const compressedStream = new PdfStream(obj, compressed);
|
|
7706
7705
|
compressedStream.set("Filter", PdfName.of("FlateDecode"));
|
|
@@ -7773,7 +7772,7 @@ function encryptStreamDict(stream, ctx) {
|
|
|
7773
7772
|
* %%EOF
|
|
7774
7773
|
* ```
|
|
7775
7774
|
*/
|
|
7776
|
-
|
|
7775
|
+
function writeComplete(registry, options) {
|
|
7777
7776
|
const writer = new ByteWriter();
|
|
7778
7777
|
const compress = options.compressStreams ?? true;
|
|
7779
7778
|
const version$1 = options.version ?? "1.7";
|
|
@@ -7790,7 +7789,7 @@ async function writeComplete(registry, options) {
|
|
|
7790
7789
|
const allObjects = /* @__PURE__ */ new Map();
|
|
7791
7790
|
for (const [ref, obj] of registry.entries()) allObjects.set(ref, obj);
|
|
7792
7791
|
for (const [ref, obj] of allObjects) {
|
|
7793
|
-
let prepared =
|
|
7792
|
+
let prepared = prepareObjectForWrite(obj, compress);
|
|
7794
7793
|
if (options.securityHandler && options.encrypt && ref !== options.encrypt) prepared = encryptObject(prepared, {
|
|
7795
7794
|
handler: options.securityHandler,
|
|
7796
7795
|
objectNumber: ref.objectNumber,
|
|
@@ -7863,7 +7862,7 @@ async function writeComplete(registry, options) {
|
|
|
7863
7862
|
* %%EOF
|
|
7864
7863
|
* ```
|
|
7865
7864
|
*/
|
|
7866
|
-
|
|
7865
|
+
function writeIncremental(registry, options) {
|
|
7867
7866
|
const changes = collectChanges(registry);
|
|
7868
7867
|
if (changes.modified.size === 0 && changes.created.size === 0) return {
|
|
7869
7868
|
bytes: options.originalBytes,
|
|
@@ -7875,7 +7874,7 @@ async function writeIncremental(registry, options) {
|
|
|
7875
7874
|
if (lastByte !== LF && lastByte !== CR) writer.writeByte(10);
|
|
7876
7875
|
const offsets = /* @__PURE__ */ new Map();
|
|
7877
7876
|
for (const [ref, obj] of changes.modified) {
|
|
7878
|
-
let prepared =
|
|
7877
|
+
let prepared = prepareObjectForWrite(obj, compress);
|
|
7879
7878
|
if (options.securityHandler && options.encrypt && ref !== options.encrypt) prepared = encryptObject(prepared, {
|
|
7880
7879
|
handler: options.securityHandler,
|
|
7881
7880
|
objectNumber: ref.objectNumber,
|
|
@@ -7888,7 +7887,7 @@ async function writeIncremental(registry, options) {
|
|
|
7888
7887
|
writeIndirectObject(writer, ref, prepared);
|
|
7889
7888
|
}
|
|
7890
7889
|
for (const [ref, obj] of changes.created) {
|
|
7891
|
-
let prepared =
|
|
7890
|
+
let prepared = prepareObjectForWrite(obj, compress);
|
|
7892
7891
|
if (options.securityHandler && options.encrypt && ref !== options.encrypt) prepared = encryptObject(prepared, {
|
|
7893
7892
|
handler: options.securityHandler,
|
|
7894
7893
|
objectNumber: ref.objectNumber,
|
|
@@ -8035,17 +8034,17 @@ function decodeFilename(str) {
|
|
|
8035
8034
|
*
|
|
8036
8035
|
* @returns The stream if found, null if external reference or missing
|
|
8037
8036
|
*/
|
|
8038
|
-
|
|
8037
|
+
function getEmbeddedFileStream(fileSpec, resolver) {
|
|
8039
8038
|
const efEntry = fileSpec.get("EF");
|
|
8040
8039
|
let ef = null;
|
|
8041
8040
|
if (efEntry instanceof PdfRef) {
|
|
8042
|
-
const resolved =
|
|
8041
|
+
const resolved = resolver(efEntry);
|
|
8043
8042
|
if (resolved instanceof PdfDict) ef = resolved;
|
|
8044
8043
|
} else if (efEntry instanceof PdfDict) ef = efEntry;
|
|
8045
8044
|
if (!ef) return null;
|
|
8046
8045
|
const streamRef = ef.getRef("F") ?? ef.getRef("UF");
|
|
8047
8046
|
if (!streamRef) return null;
|
|
8048
|
-
const stream =
|
|
8047
|
+
const stream = resolver(streamRef);
|
|
8049
8048
|
if (stream instanceof PdfStream) return stream;
|
|
8050
8049
|
return null;
|
|
8051
8050
|
}
|
|
@@ -8057,8 +8056,8 @@ async function getEmbeddedFileStream(fileSpec, resolver) {
|
|
|
8057
8056
|
* @param resolver Function to resolve references
|
|
8058
8057
|
* @returns AttachmentInfo or null if external file reference
|
|
8059
8058
|
*/
|
|
8060
|
-
|
|
8061
|
-
const stream =
|
|
8059
|
+
function parseFileSpec(fileSpec, name, resolver) {
|
|
8060
|
+
const stream = getEmbeddedFileStream(fileSpec, resolver);
|
|
8062
8061
|
if (!stream) return null;
|
|
8063
8062
|
const info = {
|
|
8064
8063
|
name,
|
|
@@ -8071,7 +8070,7 @@ async function parseFileSpec(fileSpec, name, resolver) {
|
|
|
8071
8070
|
const paramsEntry = stream.get("Params");
|
|
8072
8071
|
let params = null;
|
|
8073
8072
|
if (paramsEntry instanceof PdfRef) {
|
|
8074
|
-
const resolved =
|
|
8073
|
+
const resolved = resolver(paramsEntry);
|
|
8075
8074
|
if (resolved instanceof PdfDict) params = resolved;
|
|
8076
8075
|
} else if (paramsEntry instanceof PdfDict) params = paramsEntry;
|
|
8077
8076
|
if (params) {
|
|
@@ -8082,7 +8081,7 @@ async function parseFileSpec(fileSpec, name, resolver) {
|
|
|
8082
8081
|
const modDate = params.getString("ModDate");
|
|
8083
8082
|
if (modDate) info.modifiedAt = parsePdfDate(modDate.asString());
|
|
8084
8083
|
}
|
|
8085
|
-
if (info.size === void 0) info.size =
|
|
8084
|
+
if (info.size === void 0) info.size = stream.getDecodedData().length;
|
|
8086
8085
|
return info;
|
|
8087
8086
|
}
|
|
8088
8087
|
/**
|
|
@@ -8185,7 +8184,7 @@ var NameTree = class {
|
|
|
8185
8184
|
*
|
|
8186
8185
|
* @returns The value if found, null otherwise
|
|
8187
8186
|
*/
|
|
8188
|
-
|
|
8187
|
+
get(key$1) {
|
|
8189
8188
|
let node = this.root;
|
|
8190
8189
|
let depth = 0;
|
|
8191
8190
|
while (node.has("Kids")) {
|
|
@@ -8205,7 +8204,7 @@ var NameTree = class {
|
|
|
8205
8204
|
lo$1 = mid + 1;
|
|
8206
8205
|
continue;
|
|
8207
8206
|
}
|
|
8208
|
-
const kid =
|
|
8207
|
+
const kid = this.resolver(kidRef);
|
|
8209
8208
|
if (!(kid instanceof PdfDict)) {
|
|
8210
8209
|
lo$1 = mid + 1;
|
|
8211
8210
|
continue;
|
|
@@ -8263,14 +8262,14 @@ var NameTree = class {
|
|
|
8263
8262
|
/**
|
|
8264
8263
|
* Check if a key exists in the tree.
|
|
8265
8264
|
*/
|
|
8266
|
-
|
|
8267
|
-
return
|
|
8265
|
+
has(key$1) {
|
|
8266
|
+
return this.get(key$1) !== null;
|
|
8268
8267
|
}
|
|
8269
8268
|
/**
|
|
8270
8269
|
* Iterate all entries (lazy, yields [key, value] pairs).
|
|
8271
8270
|
* Uses BFS traversal with cycle detection.
|
|
8272
8271
|
*/
|
|
8273
|
-
|
|
8272
|
+
*entries() {
|
|
8274
8273
|
const visited = /* @__PURE__ */ new Set();
|
|
8275
8274
|
const queue = [{
|
|
8276
8275
|
node: this.root,
|
|
@@ -8292,7 +8291,7 @@ var NameTree = class {
|
|
|
8292
8291
|
continue;
|
|
8293
8292
|
}
|
|
8294
8293
|
visited.add(refKey$1);
|
|
8295
|
-
const kid =
|
|
8294
|
+
const kid = this.resolver(kidRef);
|
|
8296
8295
|
if (kid instanceof PdfDict) queue.push({
|
|
8297
8296
|
node: kid,
|
|
8298
8297
|
depth: depth + 1
|
|
@@ -8304,7 +8303,7 @@ var NameTree = class {
|
|
|
8304
8303
|
const key$1 = extractKey(names.at(i));
|
|
8305
8304
|
if (key$1 === null) continue;
|
|
8306
8305
|
let value = names.at(i + 1) ?? null;
|
|
8307
|
-
if (value instanceof PdfRef) value =
|
|
8306
|
+
if (value instanceof PdfRef) value = this.resolver(value);
|
|
8308
8307
|
if (value !== null && value !== void 0) yield [key$1, value];
|
|
8309
8308
|
}
|
|
8310
8309
|
}
|
|
@@ -8313,10 +8312,10 @@ var NameTree = class {
|
|
|
8313
8312
|
/**
|
|
8314
8313
|
* Load all entries into a Map (cached after first call).
|
|
8315
8314
|
*/
|
|
8316
|
-
|
|
8315
|
+
getAll() {
|
|
8317
8316
|
if (this.cache) return this.cache;
|
|
8318
8317
|
const result = /* @__PURE__ */ new Map();
|
|
8319
|
-
for
|
|
8318
|
+
for (const [key$1, value] of this.entries()) result.set(key$1, value);
|
|
8320
8319
|
this.cache = result;
|
|
8321
8320
|
return result;
|
|
8322
8321
|
}
|
|
@@ -8404,13 +8403,13 @@ var PDFAttachments = class {
|
|
|
8404
8403
|
* }
|
|
8405
8404
|
* ```
|
|
8406
8405
|
*/
|
|
8407
|
-
|
|
8406
|
+
list() {
|
|
8408
8407
|
const result = /* @__PURE__ */ new Map();
|
|
8409
|
-
const tree =
|
|
8408
|
+
const tree = this.ctx.catalog.getEmbeddedFilesTree();
|
|
8410
8409
|
if (!tree) return result;
|
|
8411
|
-
for
|
|
8410
|
+
for (const [name, value] of tree.entries()) {
|
|
8412
8411
|
if (!(value instanceof PdfDict)) continue;
|
|
8413
|
-
const info =
|
|
8412
|
+
const info = parseFileSpec(value, name, (ref) => this.ctx.registry.resolve(ref));
|
|
8414
8413
|
if (info) result.set(name, info);
|
|
8415
8414
|
else this.ctx.registry.addWarning(`Attachment "${name}" is an external file reference (not embedded)`);
|
|
8416
8415
|
}
|
|
@@ -8431,12 +8430,12 @@ var PDFAttachments = class {
|
|
|
8431
8430
|
* }
|
|
8432
8431
|
* ```
|
|
8433
8432
|
*/
|
|
8434
|
-
|
|
8435
|
-
const tree =
|
|
8433
|
+
get(name) {
|
|
8434
|
+
const tree = this.ctx.catalog.getEmbeddedFilesTree();
|
|
8436
8435
|
if (!tree) return null;
|
|
8437
|
-
const fileSpec =
|
|
8436
|
+
const fileSpec = tree.get(name);
|
|
8438
8437
|
if (!(fileSpec instanceof PdfDict)) return null;
|
|
8439
|
-
const stream =
|
|
8438
|
+
const stream = getEmbeddedFileStream(fileSpec, (ref) => this.ctx.registry.resolve(ref));
|
|
8440
8439
|
if (!stream) return null;
|
|
8441
8440
|
return stream.getDecodedData();
|
|
8442
8441
|
}
|
|
@@ -8453,8 +8452,8 @@ var PDFAttachments = class {
|
|
|
8453
8452
|
* }
|
|
8454
8453
|
* ```
|
|
8455
8454
|
*/
|
|
8456
|
-
|
|
8457
|
-
const tree =
|
|
8455
|
+
has(name) {
|
|
8456
|
+
const tree = this.ctx.catalog.getEmbeddedFilesTree();
|
|
8458
8457
|
if (!tree) return false;
|
|
8459
8458
|
return tree.has(name);
|
|
8460
8459
|
}
|
|
@@ -8481,21 +8480,21 @@ var PDFAttachments = class {
|
|
|
8481
8480
|
* await pdf.attachments.add("report.pdf", newBytes, { overwrite: true });
|
|
8482
8481
|
* ```
|
|
8483
8482
|
*/
|
|
8484
|
-
|
|
8485
|
-
if (!options.overwrite &&
|
|
8483
|
+
add(name, data, options = {}) {
|
|
8484
|
+
if (!options.overwrite && this.has(name)) throw new Error(`Attachment "${name}" already exists. Use { overwrite: true } to replace.`);
|
|
8486
8485
|
const embeddedFileStream = createEmbeddedFileStream(data, name, options);
|
|
8487
8486
|
const fileSpec = createFileSpec(name, this.ctx.registry.register(embeddedFileStream), options);
|
|
8488
8487
|
const fileSpecRef = this.ctx.registry.register(fileSpec);
|
|
8489
8488
|
const existingAttachments = [];
|
|
8490
|
-
const tree =
|
|
8491
|
-
if (tree) for
|
|
8489
|
+
const tree = this.ctx.catalog.getEmbeddedFilesTree();
|
|
8490
|
+
if (tree) for (const [key$1, value] of tree.entries()) {
|
|
8492
8491
|
if (key$1 === name && options.overwrite) continue;
|
|
8493
8492
|
const ref = this.ctx.registry.getRef(value);
|
|
8494
8493
|
if (ref) existingAttachments.push([key$1, ref]);
|
|
8495
8494
|
}
|
|
8496
8495
|
existingAttachments.push([name, fileSpecRef]);
|
|
8497
8496
|
const newNameTree = buildNameTree(existingAttachments);
|
|
8498
|
-
|
|
8497
|
+
this.ctx.catalog.setEmbeddedFilesTree(newNameTree);
|
|
8499
8498
|
}
|
|
8500
8499
|
/**
|
|
8501
8500
|
* Remove an attachment from the document.
|
|
@@ -8511,20 +8510,20 @@ var PDFAttachments = class {
|
|
|
8511
8510
|
* }
|
|
8512
8511
|
* ```
|
|
8513
8512
|
*/
|
|
8514
|
-
|
|
8515
|
-
const tree =
|
|
8513
|
+
remove(name) {
|
|
8514
|
+
const tree = this.ctx.catalog.getEmbeddedFilesTree();
|
|
8516
8515
|
if (!tree) return false;
|
|
8517
|
-
if (!
|
|
8516
|
+
if (!tree.has(name)) return false;
|
|
8518
8517
|
const remainingAttachments = [];
|
|
8519
|
-
for
|
|
8518
|
+
for (const [key$1, value] of tree.entries()) {
|
|
8520
8519
|
if (key$1 === name) continue;
|
|
8521
8520
|
const ref = this.ctx.registry.getRef(value);
|
|
8522
8521
|
if (ref) remainingAttachments.push([key$1, ref]);
|
|
8523
8522
|
}
|
|
8524
|
-
if (remainingAttachments.length === 0)
|
|
8523
|
+
if (remainingAttachments.length === 0) this.ctx.catalog.removeEmbeddedFilesTree();
|
|
8525
8524
|
else {
|
|
8526
8525
|
const newNameTree = buildNameTree(remainingAttachments);
|
|
8527
|
-
|
|
8526
|
+
this.ctx.catalog.setEmbeddedFilesTree(newNameTree);
|
|
8528
8527
|
}
|
|
8529
8528
|
return true;
|
|
8530
8529
|
}
|
|
@@ -8571,19 +8570,16 @@ var PDFCatalog = class {
|
|
|
8571
8570
|
/**
|
|
8572
8571
|
* Get the /Names dictionary.
|
|
8573
8572
|
*/
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
if (namesEntry instanceof PdfRef)
|
|
8577
|
-
const resolved = await this.registry.resolve(namesEntry);
|
|
8578
|
-
return resolved instanceof PdfDict ? resolved : null;
|
|
8579
|
-
}
|
|
8573
|
+
getNames() {
|
|
8574
|
+
let namesEntry = this.dict.get("Names");
|
|
8575
|
+
if (namesEntry instanceof PdfRef) namesEntry = this.registry.resolve(namesEntry) ?? void 0;
|
|
8580
8576
|
return namesEntry instanceof PdfDict ? namesEntry : null;
|
|
8581
8577
|
}
|
|
8582
8578
|
/**
|
|
8583
8579
|
* Get or create the /Names dictionary.
|
|
8584
8580
|
*/
|
|
8585
|
-
|
|
8586
|
-
let names =
|
|
8581
|
+
getOrCreateNames() {
|
|
8582
|
+
let names = this.getNames();
|
|
8587
8583
|
if (!names) {
|
|
8588
8584
|
names = new PdfDict();
|
|
8589
8585
|
this.dict.set("Names", this.registry.register(names));
|
|
@@ -8594,9 +8590,9 @@ var PDFCatalog = class {
|
|
|
8594
8590
|
* Get the EmbeddedFiles name tree.
|
|
8595
8591
|
* Caches the result for repeated access.
|
|
8596
8592
|
*/
|
|
8597
|
-
|
|
8593
|
+
getEmbeddedFilesTree() {
|
|
8598
8594
|
if (this._embeddedFilesTree !== void 0) return this._embeddedFilesTree;
|
|
8599
|
-
const names =
|
|
8595
|
+
const names = this.getNames();
|
|
8600
8596
|
if (!names) {
|
|
8601
8597
|
this._embeddedFilesTree = null;
|
|
8602
8598
|
return null;
|
|
@@ -8604,7 +8600,7 @@ var PDFCatalog = class {
|
|
|
8604
8600
|
const embeddedFilesEntry = names.get("EmbeddedFiles");
|
|
8605
8601
|
let embeddedFiles = null;
|
|
8606
8602
|
if (embeddedFilesEntry instanceof PdfRef) {
|
|
8607
|
-
const resolved =
|
|
8603
|
+
const resolved = this.registry.resolve(embeddedFilesEntry);
|
|
8608
8604
|
if (resolved instanceof PdfDict) embeddedFiles = resolved;
|
|
8609
8605
|
} else if (embeddedFilesEntry instanceof PdfDict) embeddedFiles = embeddedFilesEntry;
|
|
8610
8606
|
if (!embeddedFiles) {
|
|
@@ -8617,8 +8613,8 @@ var PDFCatalog = class {
|
|
|
8617
8613
|
/**
|
|
8618
8614
|
* Set the EmbeddedFiles name tree.
|
|
8619
8615
|
*/
|
|
8620
|
-
|
|
8621
|
-
const names =
|
|
8616
|
+
setEmbeddedFilesTree(treeDict) {
|
|
8617
|
+
const names = this.getOrCreateNames();
|
|
8622
8618
|
const treeRef = this.registry.register(treeDict);
|
|
8623
8619
|
names.set("EmbeddedFiles", treeRef);
|
|
8624
8620
|
this._embeddedFilesTree = void 0;
|
|
@@ -8626,8 +8622,8 @@ var PDFCatalog = class {
|
|
|
8626
8622
|
/**
|
|
8627
8623
|
* Remove the EmbeddedFiles entry from /Names.
|
|
8628
8624
|
*/
|
|
8629
|
-
|
|
8630
|
-
const names =
|
|
8625
|
+
removeEmbeddedFilesTree() {
|
|
8626
|
+
const names = this.getNames();
|
|
8631
8627
|
if (names) names.delete("EmbeddedFiles");
|
|
8632
8628
|
this._embeddedFilesTree = void 0;
|
|
8633
8629
|
}
|
|
@@ -8692,7 +8688,11 @@ var PDFContext = class {
|
|
|
8692
8688
|
return this.registry.register(obj);
|
|
8693
8689
|
}
|
|
8694
8690
|
/**
|
|
8695
|
-
* Resolve an object by reference
|
|
8691
|
+
* Resolve an object by reference.
|
|
8692
|
+
*
|
|
8693
|
+
* Synchronously resolves the reference, parsing from the in-memory
|
|
8694
|
+
* buffer if not already cached. All PDF data is loaded at parse time,
|
|
8695
|
+
* so this operation never requires I/O.
|
|
8696
8696
|
*/
|
|
8697
8697
|
resolve(ref) {
|
|
8698
8698
|
return this.registry.resolve(ref);
|
|
@@ -13516,7 +13516,7 @@ var Type1Parser = class {
|
|
|
13516
13516
|
const token = value[i];
|
|
13517
13517
|
if (token.kind === TokenKind.REAL) numbers.push(token.floatValue());
|
|
13518
13518
|
else if (token.kind === TokenKind.INTEGER) numbers.push(token.intValue());
|
|
13519
|
-
else throw new Error(`Expected INTEGER or REAL but got ${token} at array position ${i}`);
|
|
13519
|
+
else throw new Error(`Expected INTEGER or REAL but got ${token.kind} at array position ${i}`);
|
|
13520
13520
|
}
|
|
13521
13521
|
return numbers;
|
|
13522
13522
|
}
|
|
@@ -13874,7 +13874,7 @@ var Type1Parser = class {
|
|
|
13874
13874
|
break;
|
|
13875
13875
|
}
|
|
13876
13876
|
if (token.text === "def") return;
|
|
13877
|
-
throw new Error(`Found ${token} but expected ND`);
|
|
13877
|
+
throw new Error(`Found ${token.kind}:${token.text} but expected ND`);
|
|
13878
13878
|
}
|
|
13879
13879
|
/**
|
|
13880
13880
|
* Reads the sequence "noaccess put" or equivalent.
|
|
@@ -13890,7 +13890,7 @@ var Type1Parser = class {
|
|
|
13890
13890
|
break;
|
|
13891
13891
|
}
|
|
13892
13892
|
if (token.text === "put") return;
|
|
13893
|
-
throw new Error(`Found ${token} but expected NP`);
|
|
13893
|
+
throw new Error(`Found ${token.kind}:${token.text} but expected NP`);
|
|
13894
13894
|
}
|
|
13895
13895
|
/**
|
|
13896
13896
|
* Reads the next token and throws an exception if it is not of the given kind.
|
|
@@ -13898,8 +13898,8 @@ var Type1Parser = class {
|
|
|
13898
13898
|
*/
|
|
13899
13899
|
read(kind, name) {
|
|
13900
13900
|
const token = this.lexer.nextToken();
|
|
13901
|
-
if (token === null || token.kind !== kind) throw new Error(`Found ${token} but expected ${kind}`);
|
|
13902
|
-
if (name !== void 0 && token.text !== name) throw new Error(`Found ${token} but expected ${name}`);
|
|
13901
|
+
if (token === null || token.kind !== kind) throw new Error(`Found ${token?.kind ?? "null"}:${token?.text ?? ""} but expected ${kind}`);
|
|
13902
|
+
if (name !== void 0 && token.text !== name) throw new Error(`Found ${token.kind}:${token.text} but expected ${name}`);
|
|
13903
13903
|
return token;
|
|
13904
13904
|
}
|
|
13905
13905
|
/**
|
|
@@ -14210,6 +14210,7 @@ var CFFType1FontProgram = class {
|
|
|
14210
14210
|
return this.data;
|
|
14211
14211
|
}
|
|
14212
14212
|
};
|
|
14213
|
+
const isCFFType1FontProgram = (program) => program.type === "cff";
|
|
14213
14214
|
|
|
14214
14215
|
//#endregion
|
|
14215
14216
|
//#region src/fonts/font-program/cff-cid.ts
|
|
@@ -14296,6 +14297,7 @@ var CFFCIDFontProgram = class {
|
|
|
14296
14297
|
return this.data;
|
|
14297
14298
|
}
|
|
14298
14299
|
};
|
|
14300
|
+
const isCFFCIDFontProgram = (program) => program.type === "cff-cid";
|
|
14299
14301
|
|
|
14300
14302
|
//#endregion
|
|
14301
14303
|
//#region src/fonts/font-program/truetype.ts
|
|
@@ -14364,6 +14366,7 @@ var TrueTypeFontProgram = class {
|
|
|
14364
14366
|
return this.data;
|
|
14365
14367
|
}
|
|
14366
14368
|
};
|
|
14369
|
+
const isTrueTypeFontProgram = (program) => program.type === "truetype";
|
|
14367
14370
|
|
|
14368
14371
|
//#endregion
|
|
14369
14372
|
//#region src/fonts/font-program/type1.ts
|
|
@@ -14575,7 +14578,7 @@ function tryAutoDetectFontFile3(data) {
|
|
|
14575
14578
|
* Get the /Subtype from a stream dictionary.
|
|
14576
14579
|
*/
|
|
14577
14580
|
function getStreamSubtype(stream) {
|
|
14578
|
-
if (stream && stream instanceof PdfStream) return stream.
|
|
14581
|
+
if (stream && stream instanceof PdfStream) return stream.getName("Subtype")?.value;
|
|
14579
14582
|
}
|
|
14580
14583
|
/**
|
|
14581
14584
|
* Resolve a value through indirect references.
|
|
@@ -15664,7 +15667,7 @@ var TTFSubsetter = class {
|
|
|
15664
15667
|
/**
|
|
15665
15668
|
* Write the subset font to a byte array.
|
|
15666
15669
|
*/
|
|
15667
|
-
|
|
15670
|
+
write() {
|
|
15668
15671
|
if (this.glyphIds.size === 0 && this.uniToGID.size === 0) console.warn("Font subset is empty");
|
|
15669
15672
|
this.addCompoundReferences();
|
|
15670
15673
|
const sortedGids = [...this.glyphIds].sort((a, b) => a - b);
|
|
@@ -16629,13 +16632,13 @@ function generateSubsetTag() {
|
|
|
16629
16632
|
* @param options - Embedding options
|
|
16630
16633
|
* @returns All PDF objects that need to be registered
|
|
16631
16634
|
*/
|
|
16632
|
-
|
|
16635
|
+
function createFontObjects(font, options = {}) {
|
|
16633
16636
|
const program = font.program;
|
|
16634
16637
|
const subsetTag = options.subsetTag ?? generateSubsetTag();
|
|
16635
16638
|
font.setSubsetTag(subsetTag);
|
|
16636
16639
|
const fontName = `${subsetTag}+${program.postScriptName ?? "Unknown"}`;
|
|
16637
16640
|
const gidToCodePoint = font.getGidToCodePointMap();
|
|
16638
|
-
const subsetResult =
|
|
16641
|
+
const subsetResult = subsetFont(program, font.getUsedGlyphIds(), font.getCodePointToGidMap());
|
|
16639
16642
|
const toUnicodeData = buildToUnicodeCMapFromGids(gidToCodePoint);
|
|
16640
16643
|
const widthsArray = widthEntriesToPdfArray(buildWidthsArrayFromGids(gidToCodePoint, program));
|
|
16641
16644
|
const fontStreamDict = new PdfDict();
|
|
@@ -16667,7 +16670,7 @@ async function createFontObjects(font, options = {}) {
|
|
|
16667
16670
|
* @param font - The EmbeddedFont
|
|
16668
16671
|
* @returns All PDF objects that need to be registered
|
|
16669
16672
|
*/
|
|
16670
|
-
|
|
16673
|
+
function createFontObjectsFull(font) {
|
|
16671
16674
|
const program = font.program;
|
|
16672
16675
|
const fontName = program.postScriptName ?? "Unknown";
|
|
16673
16676
|
const fontTypeResult = getFontFileType(program);
|
|
@@ -16723,8 +16726,8 @@ function registerFontObjects(result, register, preAllocatedRef, registerAt) {
|
|
|
16723
16726
|
* @param usedGlyphIds - GIDs to include
|
|
16724
16727
|
* @param usedCodePoints - Code points that were used (for TTF subsetter)
|
|
16725
16728
|
*/
|
|
16726
|
-
|
|
16727
|
-
if (program
|
|
16729
|
+
function subsetFont(program, usedGlyphIds, usedCodePoints) {
|
|
16730
|
+
if (isCFFType1FontProgram(program) || isCFFCIDFontProgram(program)) {
|
|
16728
16731
|
const subsetter = new CFFSubsetter(program.font);
|
|
16729
16732
|
for (const gid of usedGlyphIds) subsetter.addGlyph(gid);
|
|
16730
16733
|
return {
|
|
@@ -16733,7 +16736,7 @@ async function subsetFont(program, usedGlyphIds, usedCodePoints) {
|
|
|
16733
16736
|
fontFileSubtype: "CIDFontType0C"
|
|
16734
16737
|
};
|
|
16735
16738
|
}
|
|
16736
|
-
if (program
|
|
16739
|
+
if (isTrueTypeFontProgram(program)) {
|
|
16737
16740
|
const ttf = program.font;
|
|
16738
16741
|
if (!ttf.getTableBytes("glyf")) return {
|
|
16739
16742
|
data: program.getData(),
|
|
@@ -16759,7 +16762,7 @@ async function subsetFont(program, usedGlyphIds, usedCodePoints) {
|
|
|
16759
16762
|
for (const codePoint of usedCodePoints.keys()) subsetter.add(codePoint);
|
|
16760
16763
|
const oldToNewGidMap = subsetter.getOldToNewGIDMap();
|
|
16761
16764
|
return {
|
|
16762
|
-
data:
|
|
16765
|
+
data: subsetter.write(),
|
|
16763
16766
|
fontFileKey: "FontFile2",
|
|
16764
16767
|
oldToNewGidMap
|
|
16765
16768
|
};
|
|
@@ -16774,11 +16777,11 @@ async function subsetFont(program, usedGlyphIds, usedCodePoints) {
|
|
|
16774
16777
|
* Get font file type without subsetting.
|
|
16775
16778
|
*/
|
|
16776
16779
|
function getFontFileType(program) {
|
|
16777
|
-
if (program
|
|
16780
|
+
if (isCFFType1FontProgram(program) || isCFFCIDFontProgram(program)) return {
|
|
16778
16781
|
fontFileKey: "FontFile3",
|
|
16779
16782
|
fontFileSubtype: "CIDFontType0C"
|
|
16780
16783
|
};
|
|
16781
|
-
if (program
|
|
16784
|
+
if (isTrueTypeFontProgram(program)) {
|
|
16782
16785
|
if (!program.font.getTableBytes("glyf")) return {
|
|
16783
16786
|
fontFileKey: "FontFile3",
|
|
16784
16787
|
fontFileSubtype: "OpenType"
|
|
@@ -17033,16 +17036,16 @@ var PDFFonts = class {
|
|
|
17033
17036
|
*
|
|
17034
17037
|
* @param subsetFonts - Whether to subset fonts (only include used glyphs)
|
|
17035
17038
|
*/
|
|
17036
|
-
|
|
17039
|
+
finalize(subsetFonts) {
|
|
17037
17040
|
if (this.finalized) return;
|
|
17038
|
-
for (const [font, ref] of this.embeddedFonts) registerFontObjects(subsetFonts && font.canSubset() ?
|
|
17041
|
+
for (const [font, ref] of this.embeddedFonts) registerFontObjects(subsetFonts && font.canSubset() ? createFontObjects(font) : createFontObjectsFull(font), (obj) => this.ctx.register(obj), ref, (allocatedRef, obj) => this.ctx.registry.registerAt(allocatedRef, obj));
|
|
17039
17042
|
this.finalized = true;
|
|
17040
17043
|
}
|
|
17041
17044
|
/**
|
|
17042
17045
|
* @deprecated Use `finalize()` instead. This method exists for backwards compatibility.
|
|
17043
17046
|
*/
|
|
17044
|
-
|
|
17045
|
-
|
|
17047
|
+
prepare() {
|
|
17048
|
+
this.finalize(true);
|
|
17046
17049
|
}
|
|
17047
17050
|
};
|
|
17048
17051
|
|
|
@@ -22852,6 +22855,9 @@ const FONT_GLYPH_WIDTHS = {
|
|
|
22852
22855
|
* /ToUnicode 11 0 R
|
|
22853
22856
|
* >>
|
|
22854
22857
|
*/
|
|
22858
|
+
const isSimpleFontSubtype = (subtype) => {
|
|
22859
|
+
return subtype === "TrueType" || subtype === "Type1" || subtype === "Type3" || subtype === "MMType1";
|
|
22860
|
+
};
|
|
22855
22861
|
/**
|
|
22856
22862
|
* SimpleFont handles single-byte encoded fonts (TrueType, Type1, Type3).
|
|
22857
22863
|
*/
|
|
@@ -22985,7 +22991,8 @@ var SimpleFont = class extends PdfFont {
|
|
|
22985
22991
|
* Parse a SimpleFont from a PDF font dictionary.
|
|
22986
22992
|
*/
|
|
22987
22993
|
function parseSimpleFont(dict, options = {}) {
|
|
22988
|
-
const
|
|
22994
|
+
const subtypeName = dict.getName("Subtype");
|
|
22995
|
+
const subtype = isSimpleFontSubtype(subtypeName?.value) ? subtypeName.value : "TrueType";
|
|
22989
22996
|
const baseFontName = dict.getName("BaseFont")?.value ?? "Unknown";
|
|
22990
22997
|
const firstChar = dict.getNumber("FirstChar")?.value ?? 0;
|
|
22991
22998
|
const lastChar = dict.getNumber("LastChar")?.value ?? 255;
|
|
@@ -23252,10 +23259,10 @@ const DEFAULT_HIGHLIGHT_COLOR = {
|
|
|
23252
23259
|
* Parses the content stream to find colors, fonts, and border widths
|
|
23253
23260
|
* so they can be reused when regenerating the appearance.
|
|
23254
23261
|
*/
|
|
23255
|
-
|
|
23262
|
+
function extractAppearanceStyle(stream) {
|
|
23256
23263
|
const style = {};
|
|
23257
23264
|
try {
|
|
23258
|
-
const data =
|
|
23265
|
+
const data = stream.getDecodedData();
|
|
23259
23266
|
const content = new TextDecoder().decode(data);
|
|
23260
23267
|
const btIndex = content.indexOf("BT");
|
|
23261
23268
|
const preBT = btIndex > 0 ? content.slice(0, btIndex) : content;
|
|
@@ -24617,11 +24624,12 @@ var WidgetAnnotation = class {
|
|
|
24617
24624
|
0,
|
|
24618
24625
|
0
|
|
24619
24626
|
];
|
|
24627
|
+
const [x1, y1, x2, y2] = arr.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
|
|
24620
24628
|
return [
|
|
24621
|
-
|
|
24622
|
-
|
|
24623
|
-
|
|
24624
|
-
|
|
24629
|
+
x1 ?? 0,
|
|
24630
|
+
y1 ?? 0,
|
|
24631
|
+
x2 ?? 0,
|
|
24632
|
+
y2 ?? 0
|
|
24625
24633
|
];
|
|
24626
24634
|
}
|
|
24627
24635
|
/**
|
|
@@ -24751,57 +24759,60 @@ var WidgetAnnotation = class {
|
|
|
24751
24759
|
* Get normal appearance stream.
|
|
24752
24760
|
* For stateful widgets (checkbox/radio), pass the state name.
|
|
24753
24761
|
*/
|
|
24754
|
-
|
|
24762
|
+
getNormalAppearance(state) {
|
|
24755
24763
|
const ap = this.dict.getDict("AP");
|
|
24756
24764
|
if (!ap) return null;
|
|
24757
|
-
|
|
24765
|
+
let n = ap.get("N");
|
|
24758
24766
|
if (!n) return null;
|
|
24759
|
-
|
|
24760
|
-
if (
|
|
24761
|
-
if (
|
|
24767
|
+
if (n instanceof PdfRef) n = this.registry.resolve(n) ?? void 0;
|
|
24768
|
+
if (n instanceof PdfStream) return n;
|
|
24769
|
+
if (n instanceof PdfDict) {
|
|
24762
24770
|
const stateKey = state ?? this.appearanceState ?? "Off";
|
|
24763
|
-
|
|
24771
|
+
let stateEntry = n.get(stateKey);
|
|
24764
24772
|
if (!stateEntry) return null;
|
|
24765
|
-
|
|
24766
|
-
|
|
24773
|
+
if (stateEntry instanceof PdfRef) stateEntry = this.registry.resolve(stateEntry) ?? void 0;
|
|
24774
|
+
if (stateEntry instanceof PdfStream) return stateEntry;
|
|
24775
|
+
return null;
|
|
24767
24776
|
}
|
|
24768
24777
|
return null;
|
|
24769
24778
|
}
|
|
24770
24779
|
/**
|
|
24771
24780
|
* Get rollover appearance stream (shown on mouse hover).
|
|
24772
24781
|
*/
|
|
24773
|
-
|
|
24782
|
+
getRolloverAppearance(state) {
|
|
24774
24783
|
const ap = this.dict.getDict("AP");
|
|
24775
24784
|
if (!ap) return null;
|
|
24776
|
-
|
|
24785
|
+
let r = ap.get("R");
|
|
24777
24786
|
if (!r) return null;
|
|
24778
|
-
|
|
24779
|
-
if (
|
|
24780
|
-
if (
|
|
24787
|
+
if (r instanceof PdfRef) r = this.registry.resolve(r) ?? void 0;
|
|
24788
|
+
if (r instanceof PdfStream) return r;
|
|
24789
|
+
if (r instanceof PdfDict) {
|
|
24781
24790
|
const stateKey = state ?? this.appearanceState ?? "Off";
|
|
24782
|
-
|
|
24791
|
+
let stateEntry = r.get(stateKey);
|
|
24783
24792
|
if (!stateEntry) return null;
|
|
24784
|
-
|
|
24785
|
-
|
|
24793
|
+
if (stateEntry instanceof PdfRef) stateEntry = this.registry.resolve(stateEntry) ?? void 0;
|
|
24794
|
+
if (stateEntry instanceof PdfStream) return stateEntry;
|
|
24795
|
+
return null;
|
|
24786
24796
|
}
|
|
24787
24797
|
return null;
|
|
24788
24798
|
}
|
|
24789
24799
|
/**
|
|
24790
24800
|
* Get down appearance stream (shown when clicked).
|
|
24791
24801
|
*/
|
|
24792
|
-
|
|
24802
|
+
getDownAppearance(state) {
|
|
24793
24803
|
const ap = this.dict.getDict("AP");
|
|
24794
24804
|
if (!ap) return null;
|
|
24795
|
-
|
|
24805
|
+
let d = ap.get("D");
|
|
24796
24806
|
if (!d) return null;
|
|
24797
|
-
|
|
24798
|
-
if (
|
|
24799
|
-
if (
|
|
24807
|
+
if (d instanceof PdfRef) d = this.registry.resolve(d) ?? void 0;
|
|
24808
|
+
if (d instanceof PdfStream) return d;
|
|
24809
|
+
if (d instanceof PdfDict) {
|
|
24800
24810
|
const stateKey = state ?? this.appearanceState ?? "Off";
|
|
24801
|
-
|
|
24811
|
+
let stateEntry = d.get(stateKey);
|
|
24802
24812
|
if (!stateEntry) return null;
|
|
24803
|
-
|
|
24804
|
-
|
|
24813
|
+
if (stateEntry instanceof PdfRef) stateEntry = this.registry.resolve(stateEntry) ?? void 0;
|
|
24814
|
+
if (stateEntry instanceof PdfStream) return stateEntry;
|
|
24815
|
+
return null;
|
|
24805
24816
|
}
|
|
24806
24817
|
return null;
|
|
24807
24818
|
}
|
|
@@ -24982,7 +24993,8 @@ var FormField = class {
|
|
|
24982
24993
|
}
|
|
24983
24994
|
const parentRef = current.getRef("Parent");
|
|
24984
24995
|
if (!parentRef) break;
|
|
24985
|
-
|
|
24996
|
+
const obj = this.registry.getObject(parentRef);
|
|
24997
|
+
current = obj instanceof PdfDict ? obj : null;
|
|
24986
24998
|
}
|
|
24987
24999
|
return null;
|
|
24988
25000
|
}
|
|
@@ -25189,9 +25201,9 @@ var TerminalField = class extends FormField {
|
|
|
25189
25201
|
*
|
|
25190
25202
|
* @internal
|
|
25191
25203
|
*/
|
|
25192
|
-
|
|
25204
|
+
resolveWidgets() {
|
|
25193
25205
|
if (this.dict.has("Rect")) {
|
|
25194
|
-
|
|
25206
|
+
this.resolveMK(this.dict);
|
|
25195
25207
|
this._widgets = [new WidgetAnnotation(this.dict, this.ref, this.registry)];
|
|
25196
25208
|
return;
|
|
25197
25209
|
}
|
|
@@ -25205,10 +25217,10 @@ var TerminalField = class extends FormField {
|
|
|
25205
25217
|
const item = kids.at(i);
|
|
25206
25218
|
const ref = item instanceof PdfRef ? item : null;
|
|
25207
25219
|
let widgetDict = null;
|
|
25208
|
-
if (ref) widgetDict =
|
|
25220
|
+
if (ref) widgetDict = this.registry.resolve(ref);
|
|
25209
25221
|
else if (item instanceof PdfDict) widgetDict = item;
|
|
25210
25222
|
if (widgetDict instanceof PdfDict) {
|
|
25211
|
-
|
|
25223
|
+
this.resolveMK(widgetDict);
|
|
25212
25224
|
widgets.push(new WidgetAnnotation(widgetDict, ref, this.registry));
|
|
25213
25225
|
}
|
|
25214
25226
|
}
|
|
@@ -25218,9 +25230,9 @@ var TerminalField = class extends FormField {
|
|
|
25218
25230
|
* Resolve MK dictionary if it's a reference.
|
|
25219
25231
|
* This ensures getAppearanceCharacteristics() can work synchronously.
|
|
25220
25232
|
*/
|
|
25221
|
-
|
|
25233
|
+
resolveMK(dict) {
|
|
25222
25234
|
const mkEntry = dict.get("MK");
|
|
25223
|
-
if (mkEntry instanceof PdfRef)
|
|
25235
|
+
if (mkEntry instanceof PdfRef) this.registry.resolve(mkEntry);
|
|
25224
25236
|
}
|
|
25225
25237
|
/**
|
|
25226
25238
|
* Add a widget to this field's /Kids array.
|
|
@@ -25250,12 +25262,12 @@ var TerminalField = class extends FormField {
|
|
|
25250
25262
|
* This method is async because it regenerates the field's appearance
|
|
25251
25263
|
* stream after resetting the value.
|
|
25252
25264
|
*/
|
|
25253
|
-
|
|
25265
|
+
resetValue() {
|
|
25254
25266
|
const dv = this.getInheritable("DV");
|
|
25255
25267
|
if (dv) this.dict.set("V", dv);
|
|
25256
25268
|
else this.dict.delete("V");
|
|
25257
25269
|
this.needsAppearanceUpdate = true;
|
|
25258
|
-
|
|
25270
|
+
this.applyChange();
|
|
25259
25271
|
}
|
|
25260
25272
|
/**
|
|
25261
25273
|
* Check read-only and throw if set.
|
|
@@ -25271,8 +25283,8 @@ var TerminalField = class extends FormField {
|
|
|
25271
25283
|
*
|
|
25272
25284
|
* @internal
|
|
25273
25285
|
*/
|
|
25274
|
-
|
|
25275
|
-
if (this.acroForm.updateFieldAppearance)
|
|
25286
|
+
applyChange() {
|
|
25287
|
+
if (this.acroForm.updateFieldAppearance) this.acroForm.updateFieldAppearance(this);
|
|
25276
25288
|
this.needsAppearanceUpdate = false;
|
|
25277
25289
|
}
|
|
25278
25290
|
};
|
|
@@ -25333,14 +25345,14 @@ var CheckboxField = class extends TerminalField {
|
|
|
25333
25345
|
/**
|
|
25334
25346
|
* Check the checkbox (sets to the on-value).
|
|
25335
25347
|
*/
|
|
25336
|
-
|
|
25337
|
-
|
|
25348
|
+
check() {
|
|
25349
|
+
this.setValue(this.getOnValue());
|
|
25338
25350
|
}
|
|
25339
25351
|
/**
|
|
25340
25352
|
* Uncheck the checkbox (sets to "Off").
|
|
25341
25353
|
*/
|
|
25342
|
-
|
|
25343
|
-
|
|
25354
|
+
uncheck() {
|
|
25355
|
+
this.setValue("Off");
|
|
25344
25356
|
}
|
|
25345
25357
|
/**
|
|
25346
25358
|
* Set the checkbox value.
|
|
@@ -25351,7 +25363,7 @@ var CheckboxField = class extends TerminalField {
|
|
|
25351
25363
|
* @param value "Off" or one of the on-values
|
|
25352
25364
|
* @throws {Error} if field is read-only or value is invalid
|
|
25353
25365
|
*/
|
|
25354
|
-
|
|
25366
|
+
setValue(value) {
|
|
25355
25367
|
this.assertWritable();
|
|
25356
25368
|
if (value !== "Off" && !this.getOnValues().includes(value)) throw new Error(`Invalid value "${value}" for checkbox "${this.name}"`);
|
|
25357
25369
|
this.dict.set("V", PdfName.of(value));
|
|
@@ -25360,7 +25372,7 @@ var CheckboxField = class extends TerminalField {
|
|
|
25360
25372
|
widget.setAppearanceState(state);
|
|
25361
25373
|
}
|
|
25362
25374
|
this.needsAppearanceUpdate = true;
|
|
25363
|
-
|
|
25375
|
+
this.applyChange();
|
|
25364
25376
|
}
|
|
25365
25377
|
};
|
|
25366
25378
|
|
|
@@ -25460,14 +25472,14 @@ var DropdownField = class extends TerminalField {
|
|
|
25460
25472
|
* @param value The value to select
|
|
25461
25473
|
* @throws {Error} if field is read-only or value is invalid (for non-editable dropdowns)
|
|
25462
25474
|
*/
|
|
25463
|
-
|
|
25475
|
+
setValue(value) {
|
|
25464
25476
|
this.assertWritable();
|
|
25465
25477
|
if (!this.isEditable) {
|
|
25466
25478
|
if (!this.getOptions().some((o) => o.value === value)) throw new Error(`Invalid value "${value}" for dropdown "${this.name}"`);
|
|
25467
25479
|
}
|
|
25468
25480
|
this.dict.set("V", PdfString.fromString(value));
|
|
25469
25481
|
this.needsAppearanceUpdate = true;
|
|
25470
|
-
|
|
25482
|
+
this.applyChange();
|
|
25471
25483
|
}
|
|
25472
25484
|
};
|
|
25473
25485
|
/**
|
|
@@ -25549,7 +25561,7 @@ var ListBoxField = class extends TerminalField {
|
|
|
25549
25561
|
* @param values Array of values to select
|
|
25550
25562
|
* @throws {Error} if field is read-only, multiple selection not allowed, or values are invalid
|
|
25551
25563
|
*/
|
|
25552
|
-
|
|
25564
|
+
setValue(values) {
|
|
25553
25565
|
this.assertWritable();
|
|
25554
25566
|
if (!this.isMultiSelect && values.length > 1) throw new Error(`Field "${this.name}" does not allow multiple selection`);
|
|
25555
25567
|
const options = this.getOptions();
|
|
@@ -25563,7 +25575,7 @@ var ListBoxField = class extends TerminalField {
|
|
|
25563
25575
|
else this.dict.delete("I");
|
|
25564
25576
|
}
|
|
25565
25577
|
this.needsAppearanceUpdate = true;
|
|
25566
|
-
|
|
25578
|
+
this.applyChange();
|
|
25567
25579
|
}
|
|
25568
25580
|
};
|
|
25569
25581
|
|
|
@@ -25701,7 +25713,7 @@ var RadioField = class extends TerminalField {
|
|
|
25701
25713
|
* @param option One of getOptions() or null to deselect
|
|
25702
25714
|
* @throws {Error} if field is read-only, option is invalid, or deselection not allowed
|
|
25703
25715
|
*/
|
|
25704
|
-
|
|
25716
|
+
setValue(option) {
|
|
25705
25717
|
this.assertWritable();
|
|
25706
25718
|
let value;
|
|
25707
25719
|
if (option === null) {
|
|
@@ -25717,7 +25729,7 @@ var RadioField = class extends TerminalField {
|
|
|
25717
25729
|
widget.setAppearanceState(state);
|
|
25718
25730
|
}
|
|
25719
25731
|
this.needsAppearanceUpdate = true;
|
|
25720
|
-
|
|
25732
|
+
this.applyChange();
|
|
25721
25733
|
}
|
|
25722
25734
|
};
|
|
25723
25735
|
|
|
@@ -25789,12 +25801,12 @@ var TextField = class extends TerminalField {
|
|
|
25789
25801
|
* @param value The new text value
|
|
25790
25802
|
* @throws {Error} if field is read-only
|
|
25791
25803
|
*/
|
|
25792
|
-
|
|
25804
|
+
setValue(value) {
|
|
25793
25805
|
this.assertWritable();
|
|
25794
25806
|
const finalValue = this.maxLength > 0 ? value.slice(0, this.maxLength) : value;
|
|
25795
25807
|
this.dict.set("V", PdfString.fromString(finalValue));
|
|
25796
25808
|
this.needsAppearanceUpdate = true;
|
|
25797
|
-
|
|
25809
|
+
this.applyChange();
|
|
25798
25810
|
}
|
|
25799
25811
|
};
|
|
25800
25812
|
|
|
@@ -25855,10 +25867,11 @@ function getInheritableFieldNumber(dict, key$1, registry) {
|
|
|
25855
25867
|
if (visited.has(current)) break;
|
|
25856
25868
|
visited.add(current);
|
|
25857
25869
|
const value = current.get(key$1);
|
|
25858
|
-
if (value
|
|
25870
|
+
if (value instanceof PdfNumber) return value.value;
|
|
25859
25871
|
const parentRef = current.getRef("Parent");
|
|
25860
25872
|
if (!parentRef) break;
|
|
25861
|
-
|
|
25873
|
+
const obj = registry.getObject(parentRef);
|
|
25874
|
+
current = obj instanceof PdfDict ? obj : null;
|
|
25862
25875
|
}
|
|
25863
25876
|
return 0;
|
|
25864
25877
|
}
|
|
@@ -25912,7 +25925,7 @@ var FieldTree = class FieldTree {
|
|
|
25912
25925
|
* @param registry The object registry for resolving references
|
|
25913
25926
|
* @returns A fully-loaded FieldTree
|
|
25914
25927
|
*/
|
|
25915
|
-
static
|
|
25928
|
+
static load(acroForm, registry) {
|
|
25916
25929
|
const fieldsArray = acroForm.getDict().getArray("Fields");
|
|
25917
25930
|
if (!fieldsArray) return new FieldTree([]);
|
|
25918
25931
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -25926,7 +25939,8 @@ var FieldTree = class FieldTree {
|
|
|
25926
25939
|
while (queue.length > 0) {
|
|
25927
25940
|
const entry = queue.shift();
|
|
25928
25941
|
if (!entry) continue;
|
|
25929
|
-
const {
|
|
25942
|
+
const { parentName, parent } = entry;
|
|
25943
|
+
let { item } = entry;
|
|
25930
25944
|
const ref = item instanceof PdfRef ? item : null;
|
|
25931
25945
|
const refKey$1 = ref ? `${ref.objectNumber}:${ref.generation}` : "";
|
|
25932
25946
|
if (refKey$1 && visited.has(refKey$1)) {
|
|
@@ -25935,16 +25949,14 @@ var FieldTree = class FieldTree {
|
|
|
25935
25949
|
}
|
|
25936
25950
|
if (refKey$1) visited.add(refKey$1);
|
|
25937
25951
|
let fieldDict = null;
|
|
25938
|
-
if (item instanceof PdfRef)
|
|
25939
|
-
|
|
25940
|
-
if (resolved instanceof PdfDict) fieldDict = resolved;
|
|
25941
|
-
} else if (item instanceof PdfDict) fieldDict = item;
|
|
25952
|
+
if (item instanceof PdfRef) item = registry.resolve(item) ?? void 0;
|
|
25953
|
+
if (item instanceof PdfDict) fieldDict = item;
|
|
25942
25954
|
if (!fieldDict) continue;
|
|
25943
25955
|
const partialName = fieldDict.getString("T")?.asString() ?? "";
|
|
25944
25956
|
const fullName = parentName ? partialName ? `${parentName}.${partialName}` : parentName : partialName;
|
|
25945
|
-
if (
|
|
25957
|
+
if (checkIsTerminalField(fieldDict, registry)) {
|
|
25946
25958
|
const field = createFormField(fieldDict, ref, registry, acroForm, fullName);
|
|
25947
|
-
|
|
25959
|
+
field.resolveWidgets();
|
|
25948
25960
|
field.parent = parent;
|
|
25949
25961
|
fields.push(field);
|
|
25950
25962
|
if (parent instanceof NonTerminalField) parent.addChild(field);
|
|
@@ -25974,7 +25986,7 @@ var FieldTree = class FieldTree {
|
|
|
25974
25986
|
* Iterate over only terminal fields (those that hold values).
|
|
25975
25987
|
*/
|
|
25976
25988
|
*terminalFields() {
|
|
25977
|
-
for (const field of this.fields) if (
|
|
25989
|
+
for (const field of this.fields) if (field instanceof TerminalField) yield field;
|
|
25978
25990
|
}
|
|
25979
25991
|
/**
|
|
25980
25992
|
* Get all fields as an array.
|
|
@@ -25986,7 +25998,7 @@ var FieldTree = class FieldTree {
|
|
|
25986
25998
|
* Get all terminal fields as an array.
|
|
25987
25999
|
*/
|
|
25988
26000
|
getTerminalFields() {
|
|
25989
|
-
return this.fields.filter((f) =>
|
|
26001
|
+
return this.fields.filter((f) => f instanceof TerminalField);
|
|
25990
26002
|
}
|
|
25991
26003
|
/**
|
|
25992
26004
|
* Find a field by fully-qualified name.
|
|
@@ -25999,7 +26011,7 @@ var FieldTree = class FieldTree {
|
|
|
25999
26011
|
*/
|
|
26000
26012
|
findTerminalField(name) {
|
|
26001
26013
|
const field = this.findField(name);
|
|
26002
|
-
if (field &&
|
|
26014
|
+
if (field && field instanceof TerminalField) return field;
|
|
26003
26015
|
return null;
|
|
26004
26016
|
}
|
|
26005
26017
|
/**
|
|
@@ -26022,16 +26034,14 @@ var FieldTree = class FieldTree {
|
|
|
26022
26034
|
* - It has no /Kids, OR
|
|
26023
26035
|
* - Its /Kids contain widgets (no /T) rather than child fields (have /T)
|
|
26024
26036
|
*/
|
|
26025
|
-
|
|
26037
|
+
function checkIsTerminalField(dict, registry) {
|
|
26026
26038
|
const kids = dict.getArray("Kids");
|
|
26027
26039
|
if (!kids || kids.length === 0) return true;
|
|
26028
|
-
|
|
26040
|
+
let firstKid = kids.at(0);
|
|
26029
26041
|
if (!firstKid) return true;
|
|
26030
26042
|
let firstKidDict = null;
|
|
26031
|
-
if (firstKid instanceof PdfRef)
|
|
26032
|
-
|
|
26033
|
-
if (resolved instanceof PdfDict) firstKidDict = resolved;
|
|
26034
|
-
} else if (firstKid instanceof PdfDict) firstKidDict = firstKid;
|
|
26043
|
+
if (firstKid instanceof PdfRef) firstKid = registry.resolve(firstKid) ?? void 0;
|
|
26044
|
+
if (firstKid instanceof PdfDict) firstKidDict = firstKid;
|
|
26035
26045
|
if (!firstKidDict) return true;
|
|
26036
26046
|
return !firstKidDict.has("T");
|
|
26037
26047
|
}
|
|
@@ -26225,18 +26235,18 @@ var FormFlattener = class {
|
|
|
26225
26235
|
/**
|
|
26226
26236
|
* Flatten all form fields into static page content.
|
|
26227
26237
|
*/
|
|
26228
|
-
|
|
26238
|
+
flatten(options = {}) {
|
|
26229
26239
|
if (options.font || options.fontSize !== void 0) {
|
|
26230
|
-
const fields =
|
|
26240
|
+
const fields = this.form.getFields();
|
|
26231
26241
|
for (const field of fields) {
|
|
26232
26242
|
if (field.isReadOnly()) continue;
|
|
26233
26243
|
if (options.font) field.setFont(options.font);
|
|
26234
26244
|
if (options.fontSize !== void 0) field.setFontSize(options.fontSize);
|
|
26235
26245
|
}
|
|
26236
26246
|
}
|
|
26237
|
-
if (!options.skipAppearanceUpdate)
|
|
26238
|
-
const pageWidgets =
|
|
26239
|
-
for (const { pageRef, widgets } of pageWidgets.values())
|
|
26247
|
+
if (!options.skipAppearanceUpdate) this.form.updateAppearances({ forceRegenerate: options.regenerateAppearances });
|
|
26248
|
+
const pageWidgets = this.collectWidgetsByPage();
|
|
26249
|
+
for (const { pageRef, widgets } of pageWidgets.values()) this.flattenWidgetsOnPage(pageRef, widgets);
|
|
26240
26250
|
const dict = this.form.getDict();
|
|
26241
26251
|
dict.set("Fields", new PdfArray([]));
|
|
26242
26252
|
dict.delete("NeedAppearances");
|
|
@@ -26246,12 +26256,12 @@ var FormFlattener = class {
|
|
|
26246
26256
|
/**
|
|
26247
26257
|
* Collect all widgets grouped by their containing page.
|
|
26248
26258
|
*/
|
|
26249
|
-
|
|
26259
|
+
collectWidgetsByPage() {
|
|
26250
26260
|
const result = /* @__PURE__ */ new Map();
|
|
26251
|
-
const fields =
|
|
26261
|
+
const fields = this.form.getFields();
|
|
26252
26262
|
for (const field of fields) for (const widget of field.getWidgets()) {
|
|
26253
26263
|
let pageRef = widget.pageRef;
|
|
26254
|
-
if (!pageRef) pageRef =
|
|
26264
|
+
if (!pageRef) pageRef = this.findPageForWidget(widget);
|
|
26255
26265
|
if (!pageRef) {
|
|
26256
26266
|
this.registry.addWarning(`Widget without page reference for field "${field.name}"`);
|
|
26257
26267
|
continue;
|
|
@@ -26275,7 +26285,7 @@ var FormFlattener = class {
|
|
|
26275
26285
|
*
|
|
26276
26286
|
* Uses the PageTree if available for efficient page iteration.
|
|
26277
26287
|
*/
|
|
26278
|
-
|
|
26288
|
+
findPageForWidget(widget) {
|
|
26279
26289
|
if (!widget.ref) return null;
|
|
26280
26290
|
if (!this.pageTree) {
|
|
26281
26291
|
this.registry.addWarning("No page tree available; cannot find page for widget without /P");
|
|
@@ -26283,7 +26293,7 @@ var FormFlattener = class {
|
|
|
26283
26293
|
}
|
|
26284
26294
|
const pageRefs = this.pageTree.getPages();
|
|
26285
26295
|
for (const pageRef of pageRefs) {
|
|
26286
|
-
const pageDict =
|
|
26296
|
+
const pageDict = this.registry.resolve(pageRef);
|
|
26287
26297
|
if (!(pageDict instanceof PdfDict)) continue;
|
|
26288
26298
|
const annots = pageDict.getArray("Annots");
|
|
26289
26299
|
if (!annots) continue;
|
|
@@ -26303,8 +26313,8 @@ var FormFlattener = class {
|
|
|
26303
26313
|
*
|
|
26304
26314
|
* This isolates the original page's graphics state from our flattened fields.
|
|
26305
26315
|
*/
|
|
26306
|
-
|
|
26307
|
-
const pageDict =
|
|
26316
|
+
flattenWidgetsOnPage(pageRef, widgets) {
|
|
26317
|
+
const pageDict = this.registry.resolve(pageRef);
|
|
26308
26318
|
if (!(pageDict instanceof PdfDict)) return;
|
|
26309
26319
|
let resources = pageDict.getDict("Resources");
|
|
26310
26320
|
if (!resources) {
|
|
@@ -26322,7 +26332,7 @@ var FormFlattener = class {
|
|
|
26322
26332
|
let hasVisibleWidgets = false;
|
|
26323
26333
|
for (const widget of widgets) {
|
|
26324
26334
|
if (this.isWidgetHidden(widget)) continue;
|
|
26325
|
-
const appearance =
|
|
26335
|
+
const appearance = widget.getNormalAppearance(widget.appearanceState ?? void 0);
|
|
26326
26336
|
if (!appearance) {
|
|
26327
26337
|
this.registry.addWarning("Widget without appearance stream skipped during flatten");
|
|
26328
26338
|
continue;
|
|
@@ -26338,7 +26348,7 @@ var FormFlattener = class {
|
|
|
26338
26348
|
if (widget.ref) widgetRefs.add(`${widget.ref.objectNumber} ${widget.ref.generation}`);
|
|
26339
26349
|
}
|
|
26340
26350
|
if (hasVisibleWidgets && !content.isEmpty()) this.wrapAndAppendContent(pageDict, content.toBytes());
|
|
26341
|
-
|
|
26351
|
+
this.removeAnnotations(pageDict, widgetRefs);
|
|
26342
26352
|
}
|
|
26343
26353
|
/**
|
|
26344
26354
|
* Check if appearance stream has valid dimensions.
|
|
@@ -26347,12 +26357,9 @@ var FormFlattener = class {
|
|
|
26347
26357
|
isVisibleAppearance(appearance) {
|
|
26348
26358
|
const bbox = appearance.getArray("BBox");
|
|
26349
26359
|
if (!bbox || bbox.length < 4) return false;
|
|
26350
|
-
const x1 = bbox.
|
|
26351
|
-
const
|
|
26352
|
-
const
|
|
26353
|
-
const y2 = bbox.at(3)?.value ?? 0;
|
|
26354
|
-
const width = Math.abs(x2 - x1);
|
|
26355
|
-
const height = Math.abs(y2 - y1);
|
|
26360
|
+
const [x1, y1, x2, y2] = bbox.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
|
|
26361
|
+
const width = Math.abs((x2 ?? 0) - (x1 ?? 0));
|
|
26362
|
+
const height = Math.abs((y2 ?? 0) - (y1 ?? 0));
|
|
26356
26363
|
return width > 0 && height > 0;
|
|
26357
26364
|
}
|
|
26358
26365
|
/**
|
|
@@ -26452,7 +26459,8 @@ var FormFlattener = class {
|
|
|
26452
26459
|
getAppearanceMatrix(appearance) {
|
|
26453
26460
|
const matrixArray = appearance.getArray("Matrix");
|
|
26454
26461
|
if (!matrixArray || matrixArray.length < 6) return Matrix.identity();
|
|
26455
|
-
|
|
26462
|
+
const [a, b, c, d, e, f] = matrixArray.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
|
|
26463
|
+
return new Matrix(a ?? 0, b ?? 0, c ?? 0, d ?? 0, e ?? 0, f ?? 0);
|
|
26456
26464
|
}
|
|
26457
26465
|
/**
|
|
26458
26466
|
* Get appearance BBox, with fallback.
|
|
@@ -26465,23 +26473,24 @@ var FormFlattener = class {
|
|
|
26465
26473
|
1,
|
|
26466
26474
|
1
|
|
26467
26475
|
];
|
|
26476
|
+
const [x1, y1, x2, y2] = bbox.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
|
|
26468
26477
|
return [
|
|
26469
|
-
|
|
26470
|
-
|
|
26471
|
-
|
|
26472
|
-
|
|
26478
|
+
x1 ?? 0,
|
|
26479
|
+
y1 ?? 0,
|
|
26480
|
+
x2 ?? 0,
|
|
26481
|
+
y2 ?? 0
|
|
26473
26482
|
];
|
|
26474
26483
|
}
|
|
26475
26484
|
/**
|
|
26476
26485
|
* Remove specific annotations from page.
|
|
26477
26486
|
*/
|
|
26478
|
-
|
|
26487
|
+
removeAnnotations(page, toRemove) {
|
|
26479
26488
|
const annotsEntry = page.get("Annots");
|
|
26480
26489
|
if (!annotsEntry) return;
|
|
26481
26490
|
let annots = null;
|
|
26482
26491
|
if (annotsEntry instanceof PdfArray) annots = annotsEntry;
|
|
26483
26492
|
else if (annotsEntry instanceof PdfRef) {
|
|
26484
|
-
const resolved =
|
|
26493
|
+
const resolved = this.registry.resolve(annotsEntry);
|
|
26485
26494
|
if (resolved instanceof PdfArray) annots = resolved;
|
|
26486
26495
|
}
|
|
26487
26496
|
if (!annots) return;
|
|
@@ -26548,28 +26557,24 @@ var AcroForm = class AcroForm {
|
|
|
26548
26557
|
* @param registry The object registry for resolving references
|
|
26549
26558
|
* @param pageTree Optional page tree for efficient page lookups during flattening
|
|
26550
26559
|
*/
|
|
26551
|
-
static
|
|
26552
|
-
|
|
26560
|
+
static load(catalog, registry, pageTree) {
|
|
26561
|
+
let acroFormEntry = catalog.get("AcroForm");
|
|
26553
26562
|
if (!acroFormEntry) return null;
|
|
26554
26563
|
let dict = null;
|
|
26555
|
-
if (acroFormEntry instanceof PdfRef)
|
|
26556
|
-
|
|
26557
|
-
if (resolved instanceof PdfDict) dict = resolved;
|
|
26558
|
-
} else if (acroFormEntry instanceof PdfDict) dict = acroFormEntry;
|
|
26564
|
+
if (acroFormEntry instanceof PdfRef) acroFormEntry = registry.resolve(acroFormEntry) ?? void 0;
|
|
26565
|
+
if (acroFormEntry instanceof PdfDict) dict = acroFormEntry;
|
|
26559
26566
|
if (!dict) return null;
|
|
26560
26567
|
return new AcroForm(dict, registry, pageTree ?? null);
|
|
26561
26568
|
}
|
|
26562
26569
|
/**
|
|
26563
26570
|
* Default resources dictionary (fonts, etc.).
|
|
26564
26571
|
*/
|
|
26565
|
-
|
|
26566
|
-
|
|
26572
|
+
getDefaultResources() {
|
|
26573
|
+
let dr = this.dict.get("DR");
|
|
26567
26574
|
if (!dr) return null;
|
|
26568
|
-
if (dr instanceof PdfRef)
|
|
26569
|
-
|
|
26570
|
-
|
|
26571
|
-
}
|
|
26572
|
-
return dr instanceof PdfDict ? dr : null;
|
|
26575
|
+
if (dr instanceof PdfRef) dr = this.registry.resolve(dr) ?? void 0;
|
|
26576
|
+
if (dr instanceof PdfDict) return dr;
|
|
26577
|
+
return null;
|
|
26573
26578
|
}
|
|
26574
26579
|
/**
|
|
26575
26580
|
* Default appearance string.
|
|
@@ -26615,12 +26620,12 @@ var AcroForm = class AcroForm {
|
|
|
26615
26620
|
* Get all terminal fields (flattened).
|
|
26616
26621
|
* Non-terminal fields (containers) are not included.
|
|
26617
26622
|
*/
|
|
26618
|
-
|
|
26623
|
+
getFields() {
|
|
26619
26624
|
if (this.fieldsCache) return this.fieldsCache;
|
|
26620
26625
|
const fieldsArray = this.dict.getArray("Fields");
|
|
26621
26626
|
if (!fieldsArray) return [];
|
|
26622
26627
|
const visited = /* @__PURE__ */ new Set();
|
|
26623
|
-
const fields =
|
|
26628
|
+
const fields = this.collectFields(fieldsArray, visited, "");
|
|
26624
26629
|
this.fieldsCache = fields;
|
|
26625
26630
|
return fields;
|
|
26626
26631
|
}
|
|
@@ -26628,14 +26633,14 @@ var AcroForm = class AcroForm {
|
|
|
26628
26633
|
* Get field by fully-qualified name.
|
|
26629
26634
|
* Returns null if not found.
|
|
26630
26635
|
*/
|
|
26631
|
-
|
|
26632
|
-
return
|
|
26636
|
+
getField(name) {
|
|
26637
|
+
return this.getFields().find((f) => f.name === name) ?? null;
|
|
26633
26638
|
}
|
|
26634
26639
|
/**
|
|
26635
26640
|
* Get all fields of a specific type.
|
|
26636
26641
|
*/
|
|
26637
|
-
|
|
26638
|
-
return
|
|
26642
|
+
getFieldsOfType(type) {
|
|
26643
|
+
return this.getFields().filter((f) => f.type === type);
|
|
26639
26644
|
}
|
|
26640
26645
|
/**
|
|
26641
26646
|
* Get the underlying dictionary.
|
|
@@ -26667,7 +26672,7 @@ var AcroForm = class AcroForm {
|
|
|
26667
26672
|
* }
|
|
26668
26673
|
* ```
|
|
26669
26674
|
*/
|
|
26670
|
-
|
|
26675
|
+
getFieldTree() {
|
|
26671
26676
|
return FieldTree.load(this, this.registry);
|
|
26672
26677
|
}
|
|
26673
26678
|
/**
|
|
@@ -26741,8 +26746,10 @@ var AcroForm = class AcroForm {
|
|
|
26741
26746
|
const fontName = key$1.value;
|
|
26742
26747
|
const fontObj = fonts.get(fontName);
|
|
26743
26748
|
if (fontObj) {
|
|
26744
|
-
|
|
26745
|
-
|
|
26749
|
+
if (fontObj instanceof PdfDict || fontObj instanceof PdfRef) {
|
|
26750
|
+
const existingFont = parseExistingFont(fontName, fontObj, this.registry);
|
|
26751
|
+
this.existingFontsCache.set(fontName, existingFont);
|
|
26752
|
+
}
|
|
26746
26753
|
}
|
|
26747
26754
|
}
|
|
26748
26755
|
}
|
|
@@ -26754,60 +26761,38 @@ var AcroForm = class AcroForm {
|
|
|
26754
26761
|
*
|
|
26755
26762
|
* @internal
|
|
26756
26763
|
*/
|
|
26757
|
-
|
|
26764
|
+
updateFieldAppearance(field) {
|
|
26758
26765
|
if (field.isReadOnly()) return;
|
|
26759
26766
|
const generator = new AppearanceGenerator(this, this.registry);
|
|
26760
|
-
|
|
26761
|
-
|
|
26762
|
-
|
|
26763
|
-
|
|
26764
|
-
|
|
26765
|
-
|
|
26766
|
-
|
|
26767
|
-
|
|
26768
|
-
|
|
26769
|
-
|
|
26770
|
-
|
|
26771
|
-
|
|
26772
|
-
|
|
26773
|
-
|
|
26774
|
-
|
|
26775
|
-
|
|
26776
|
-
|
|
26777
|
-
|
|
26778
|
-
|
|
26779
|
-
|
|
26780
|
-
|
|
26781
|
-
|
|
26782
|
-
|
|
26783
|
-
|
|
26784
|
-
|
|
26785
|
-
|
|
26786
|
-
|
|
26787
|
-
|
|
26788
|
-
|
|
26789
|
-
widget.setNormalAppearance(off, "Off");
|
|
26790
|
-
}
|
|
26791
|
-
break;
|
|
26792
|
-
}
|
|
26793
|
-
case "dropdown": {
|
|
26794
|
-
const dropdownField = field;
|
|
26795
|
-
for (const widget of dropdownField.getWidgets()) {
|
|
26796
|
-
const stream = generator.generateDropdownAppearance(dropdownField, widget);
|
|
26797
|
-
widget.setNormalAppearance(stream);
|
|
26798
|
-
}
|
|
26799
|
-
break;
|
|
26800
|
-
}
|
|
26801
|
-
case "listbox": {
|
|
26802
|
-
const listboxField = field;
|
|
26803
|
-
for (const widget of listboxField.getWidgets()) {
|
|
26804
|
-
const stream = generator.generateListBoxAppearance(listboxField, widget);
|
|
26805
|
-
widget.setNormalAppearance(stream);
|
|
26806
|
-
}
|
|
26807
|
-
break;
|
|
26808
|
-
}
|
|
26809
|
-
case "button": break;
|
|
26810
|
-
}
|
|
26767
|
+
if (field instanceof TextField) for (const widget of field.getWidgets()) {
|
|
26768
|
+
const existingAppearance = widget.getNormalAppearance();
|
|
26769
|
+
const existingStyle = existingAppearance ? extractAppearanceStyle(existingAppearance) : void 0;
|
|
26770
|
+
const stream = generator.generateTextAppearance(field, widget, existingStyle);
|
|
26771
|
+
widget.setNormalAppearance(stream);
|
|
26772
|
+
}
|
|
26773
|
+
if (field instanceof CheckboxField) for (const widget of field.getWidgets()) {
|
|
26774
|
+
const onValue = widget.getOnValue() ?? "Yes";
|
|
26775
|
+
if (widget.hasAppearancesForStates([onValue, "Off"])) continue;
|
|
26776
|
+
const { on, off } = generator.generateCheckboxAppearance(field, widget, onValue);
|
|
26777
|
+
widget.setNormalAppearance(on, onValue);
|
|
26778
|
+
widget.setNormalAppearance(off, "Off");
|
|
26779
|
+
}
|
|
26780
|
+
if (field instanceof RadioField) for (const widget of field.getWidgets()) {
|
|
26781
|
+
const value = widget.getOnValue() ?? "Choice";
|
|
26782
|
+
if (widget.hasAppearancesForStates([value, "Off"])) continue;
|
|
26783
|
+
const { selected, off } = generator.generateRadioAppearance(field, widget, value);
|
|
26784
|
+
widget.setNormalAppearance(selected, value);
|
|
26785
|
+
widget.setNormalAppearance(off, "Off");
|
|
26786
|
+
}
|
|
26787
|
+
if (field instanceof DropdownField) for (const widget of field.getWidgets()) {
|
|
26788
|
+
const stream = generator.generateDropdownAppearance(field, widget);
|
|
26789
|
+
widget.setNormalAppearance(stream);
|
|
26790
|
+
}
|
|
26791
|
+
if (field instanceof ListBoxField) for (const widget of field.getWidgets()) {
|
|
26792
|
+
const stream = generator.generateListBoxAppearance(field, widget);
|
|
26793
|
+
widget.setNormalAppearance(stream);
|
|
26794
|
+
}
|
|
26795
|
+
if (field instanceof ButtonField) {}
|
|
26811
26796
|
this.dict.delete("NeedAppearances");
|
|
26812
26797
|
}
|
|
26813
26798
|
/**
|
|
@@ -26818,9 +26803,9 @@ var AcroForm = class AcroForm {
|
|
|
26818
26803
|
*
|
|
26819
26804
|
* @param options.forceRegenerate Force regeneration even if appearances exist
|
|
26820
26805
|
*/
|
|
26821
|
-
|
|
26806
|
+
updateAppearances(options = {}) {
|
|
26822
26807
|
const generator = new AppearanceGenerator(this, this.registry);
|
|
26823
|
-
const fields =
|
|
26808
|
+
const fields = this.getFields();
|
|
26824
26809
|
for (const field of fields) {
|
|
26825
26810
|
if (!field.needsAppearanceUpdate) continue;
|
|
26826
26811
|
if (field.isReadOnly()) {
|
|
@@ -26828,59 +26813,37 @@ var AcroForm = class AcroForm {
|
|
|
26828
26813
|
continue;
|
|
26829
26814
|
}
|
|
26830
26815
|
const forceRegen = options.forceRegenerate ?? false;
|
|
26831
|
-
|
|
26832
|
-
|
|
26833
|
-
|
|
26834
|
-
|
|
26835
|
-
|
|
26836
|
-
|
|
26837
|
-
|
|
26838
|
-
|
|
26839
|
-
|
|
26840
|
-
|
|
26841
|
-
|
|
26842
|
-
|
|
26843
|
-
|
|
26844
|
-
|
|
26845
|
-
|
|
26846
|
-
|
|
26847
|
-
|
|
26848
|
-
|
|
26849
|
-
|
|
26850
|
-
}
|
|
26851
|
-
break;
|
|
26852
|
-
}
|
|
26853
|
-
case "radio": {
|
|
26854
|
-
const radioField = field;
|
|
26855
|
-
for (const widget of radioField.getWidgets()) {
|
|
26856
|
-
const value = widget.getOnValue() ?? "Choice";
|
|
26857
|
-
if (!forceRegen && widget.hasAppearancesForStates([value, "Off"])) continue;
|
|
26858
|
-
const { selected, off } = generator.generateRadioAppearance(radioField, widget, value);
|
|
26859
|
-
widget.setNormalAppearance(selected, value);
|
|
26860
|
-
widget.setNormalAppearance(off, "Off");
|
|
26861
|
-
}
|
|
26862
|
-
break;
|
|
26863
|
-
}
|
|
26864
|
-
case "dropdown": {
|
|
26865
|
-
const dropdownField = field;
|
|
26866
|
-
for (const widget of dropdownField.getWidgets()) {
|
|
26867
|
-
if (!forceRegen && widget.hasNormalAppearance()) continue;
|
|
26868
|
-
const stream = generator.generateDropdownAppearance(dropdownField, widget);
|
|
26869
|
-
widget.setNormalAppearance(stream);
|
|
26870
|
-
}
|
|
26871
|
-
break;
|
|
26872
|
-
}
|
|
26873
|
-
case "listbox": {
|
|
26874
|
-
const listboxField = field;
|
|
26875
|
-
for (const widget of listboxField.getWidgets()) {
|
|
26876
|
-
if (!forceRegen && widget.hasNormalAppearance()) continue;
|
|
26877
|
-
const stream = generator.generateListBoxAppearance(listboxField, widget);
|
|
26878
|
-
widget.setNormalAppearance(stream);
|
|
26879
|
-
}
|
|
26880
|
-
break;
|
|
26881
|
-
}
|
|
26882
|
-
case "button": break;
|
|
26816
|
+
if (field instanceof TextField) for (const widget of field.getWidgets()) {
|
|
26817
|
+
const existingAppearance = widget.getNormalAppearance();
|
|
26818
|
+
const existingStyle = existingAppearance ? extractAppearanceStyle(existingAppearance) : void 0;
|
|
26819
|
+
const stream = generator.generateTextAppearance(field, widget, existingStyle);
|
|
26820
|
+
widget.setNormalAppearance(stream);
|
|
26821
|
+
}
|
|
26822
|
+
if (field instanceof CheckboxField) for (const widget of field.getWidgets()) {
|
|
26823
|
+
const onValue = widget.getOnValue() ?? "Yes";
|
|
26824
|
+
if (!forceRegen && widget.hasAppearancesForStates([onValue, "Off"])) continue;
|
|
26825
|
+
const { on, off } = generator.generateCheckboxAppearance(field, widget, onValue);
|
|
26826
|
+
widget.setNormalAppearance(on, onValue);
|
|
26827
|
+
widget.setNormalAppearance(off, "Off");
|
|
26828
|
+
}
|
|
26829
|
+
if (field instanceof RadioField) for (const widget of field.getWidgets()) {
|
|
26830
|
+
const value = widget.getOnValue() ?? "Choice";
|
|
26831
|
+
if (!forceRegen && widget.hasAppearancesForStates([value, "Off"])) continue;
|
|
26832
|
+
const { selected, off } = generator.generateRadioAppearance(field, widget, value);
|
|
26833
|
+
widget.setNormalAppearance(selected, value);
|
|
26834
|
+
widget.setNormalAppearance(off, "Off");
|
|
26883
26835
|
}
|
|
26836
|
+
if (field instanceof DropdownField) for (const widget of field.getWidgets()) {
|
|
26837
|
+
if (!forceRegen && widget.hasNormalAppearance()) continue;
|
|
26838
|
+
const stream = generator.generateDropdownAppearance(field, widget);
|
|
26839
|
+
widget.setNormalAppearance(stream);
|
|
26840
|
+
}
|
|
26841
|
+
if (field instanceof ListBoxField) for (const widget of field.getWidgets()) {
|
|
26842
|
+
if (!forceRegen && widget.hasNormalAppearance()) continue;
|
|
26843
|
+
const stream = generator.generateListBoxAppearance(field, widget);
|
|
26844
|
+
widget.setNormalAppearance(stream);
|
|
26845
|
+
}
|
|
26846
|
+
if (field instanceof ButtonField) {}
|
|
26884
26847
|
field.needsAppearanceUpdate = false;
|
|
26885
26848
|
}
|
|
26886
26849
|
this.dict.delete("NeedAppearances");
|
|
@@ -26888,17 +26851,17 @@ var AcroForm = class AcroForm {
|
|
|
26888
26851
|
/**
|
|
26889
26852
|
* Mark all fields as needing appearance update.
|
|
26890
26853
|
*/
|
|
26891
|
-
|
|
26892
|
-
const fields =
|
|
26854
|
+
markAllNeedAppearanceUpdate() {
|
|
26855
|
+
const fields = this.getFields();
|
|
26893
26856
|
for (const field of fields) field.needsAppearanceUpdate = true;
|
|
26894
26857
|
}
|
|
26895
26858
|
/**
|
|
26896
26859
|
* Collect all terminal fields from a /Kids or /Fields array.
|
|
26897
26860
|
*/
|
|
26898
|
-
|
|
26861
|
+
collectFields(kids, visited, parentName) {
|
|
26899
26862
|
const fields = [];
|
|
26900
26863
|
for (let i = 0; i < kids.length; i++) {
|
|
26901
|
-
|
|
26864
|
+
let item = kids.at(i);
|
|
26902
26865
|
const ref = item instanceof PdfRef ? item : null;
|
|
26903
26866
|
const refKey$1 = ref ? `${ref.objectNumber} ${ref.generation}` : "";
|
|
26904
26867
|
if (refKey$1 && visited.has(refKey$1)) {
|
|
@@ -26907,20 +26870,18 @@ var AcroForm = class AcroForm {
|
|
|
26907
26870
|
}
|
|
26908
26871
|
if (refKey$1) visited.add(refKey$1);
|
|
26909
26872
|
let dict = null;
|
|
26910
|
-
if (item instanceof PdfRef)
|
|
26911
|
-
|
|
26912
|
-
if (resolved instanceof PdfDict) dict = resolved;
|
|
26913
|
-
} else if (item instanceof PdfDict) dict = item;
|
|
26873
|
+
if (item instanceof PdfRef) item = this.registry.resolve(item) ?? void 0;
|
|
26874
|
+
if (item instanceof PdfDict) dict = item;
|
|
26914
26875
|
if (!dict) continue;
|
|
26915
26876
|
const partialName = dict.getString("T")?.asString() ?? "";
|
|
26916
26877
|
const fullName = parentName ? partialName ? `${parentName}.${partialName}` : parentName : partialName;
|
|
26917
|
-
if (
|
|
26878
|
+
if (this.isTerminalField(dict)) {
|
|
26918
26879
|
const field = createFormField(dict, ref, this.registry, this, fullName);
|
|
26919
|
-
|
|
26880
|
+
field.resolveWidgets();
|
|
26920
26881
|
fields.push(field);
|
|
26921
26882
|
} else {
|
|
26922
26883
|
const childKids = dict.getArray("Kids");
|
|
26923
|
-
if (childKids) fields.push(...
|
|
26884
|
+
if (childKids) fields.push(...this.collectFields(childKids, visited, fullName));
|
|
26924
26885
|
}
|
|
26925
26886
|
}
|
|
26926
26887
|
return fields;
|
|
@@ -26932,16 +26893,14 @@ var AcroForm = class AcroForm {
|
|
|
26932
26893
|
* - It has no /Kids, OR
|
|
26933
26894
|
* - Its /Kids contain widgets (no /T) rather than child fields (have /T)
|
|
26934
26895
|
*/
|
|
26935
|
-
|
|
26896
|
+
isTerminalField(dict) {
|
|
26936
26897
|
const kids = dict.getArray("Kids");
|
|
26937
26898
|
if (!kids || kids.length === 0) return true;
|
|
26938
|
-
|
|
26899
|
+
let firstKid = kids.at(0);
|
|
26939
26900
|
if (!firstKid) return true;
|
|
26940
26901
|
let firstKidDict = null;
|
|
26941
|
-
if (firstKid instanceof PdfRef)
|
|
26942
|
-
|
|
26943
|
-
if (resolved instanceof PdfDict) firstKidDict = resolved;
|
|
26944
|
-
} else if (firstKid instanceof PdfDict) firstKidDict = firstKid;
|
|
26902
|
+
if (firstKid instanceof PdfRef) firstKid = this.registry.resolve(firstKid) ?? void 0;
|
|
26903
|
+
if (firstKid instanceof PdfDict) firstKidDict = firstKid;
|
|
26945
26904
|
if (!firstKidDict) return true;
|
|
26946
26905
|
return !firstKidDict.has("T");
|
|
26947
26906
|
}
|
|
@@ -27003,6 +26962,28 @@ var AcroForm = class AcroForm {
|
|
|
27003
26962
|
this.clearCache();
|
|
27004
26963
|
}
|
|
27005
26964
|
/**
|
|
26965
|
+
* Remove a field reference from the Fields array.
|
|
26966
|
+
*
|
|
26967
|
+
* This only removes the field from the AcroForm's /Fields array.
|
|
26968
|
+
* Widget removal from pages must be handled separately.
|
|
26969
|
+
*
|
|
26970
|
+
* @param fieldRef Reference to the field dictionary to remove
|
|
26971
|
+
* @returns true if the field was found and removed, false otherwise
|
|
26972
|
+
*/
|
|
26973
|
+
removeField(fieldRef) {
|
|
26974
|
+
const fieldsArray = this.dict.getArray("Fields");
|
|
26975
|
+
if (!fieldsArray) return false;
|
|
26976
|
+
for (let i = 0; i < fieldsArray.length; i++) {
|
|
26977
|
+
const item = fieldsArray.at(i);
|
|
26978
|
+
if (item instanceof PdfRef && item === fieldRef) {
|
|
26979
|
+
fieldsArray.remove(i);
|
|
26980
|
+
this.clearCache();
|
|
26981
|
+
return true;
|
|
26982
|
+
}
|
|
26983
|
+
}
|
|
26984
|
+
return false;
|
|
26985
|
+
}
|
|
26986
|
+
/**
|
|
27006
26987
|
* Flatten all form fields into static page content.
|
|
27007
26988
|
*
|
|
27008
26989
|
* This converts interactive form fields into static graphics. After flattening:
|
|
@@ -27017,8 +26998,8 @@ var AcroForm = class AcroForm {
|
|
|
27017
26998
|
*
|
|
27018
26999
|
* @param options Flattening options
|
|
27019
27000
|
*/
|
|
27020
|
-
|
|
27021
|
-
|
|
27001
|
+
flatten(options = {}) {
|
|
27002
|
+
new FormFlattener(this, this.registry, this.pageTree).flatten(options);
|
|
27022
27003
|
this.fieldsCache = null;
|
|
27023
27004
|
}
|
|
27024
27005
|
};
|
|
@@ -27196,10 +27177,10 @@ var PDFForm = class PDFForm {
|
|
|
27196
27177
|
* @param ctx The PDF context
|
|
27197
27178
|
* @returns PDFForm instance, or null if no form exists
|
|
27198
27179
|
*/
|
|
27199
|
-
static
|
|
27200
|
-
const acroForm =
|
|
27180
|
+
static load(ctx) {
|
|
27181
|
+
const acroForm = AcroForm.load(ctx.catalog.getDict(), ctx.registry, ctx.pages);
|
|
27201
27182
|
if (!acroForm) return null;
|
|
27202
|
-
return new PDFForm(acroForm, ctx,
|
|
27183
|
+
return new PDFForm(acroForm, ctx, acroForm.getFields());
|
|
27203
27184
|
}
|
|
27204
27185
|
/**
|
|
27205
27186
|
* Get all form fields.
|
|
@@ -27228,7 +27209,7 @@ var PDFForm = class PDFForm {
|
|
|
27228
27209
|
*/
|
|
27229
27210
|
getTextField(name) {
|
|
27230
27211
|
const field = this.fieldsByName.get(name);
|
|
27231
|
-
return field
|
|
27212
|
+
return field instanceof TextField ? field : void 0;
|
|
27232
27213
|
}
|
|
27233
27214
|
/**
|
|
27234
27215
|
* Get a checkbox field by name.
|
|
@@ -27237,7 +27218,7 @@ var PDFForm = class PDFForm {
|
|
|
27237
27218
|
*/
|
|
27238
27219
|
getCheckbox(name) {
|
|
27239
27220
|
const field = this.fieldsByName.get(name);
|
|
27240
|
-
return field
|
|
27221
|
+
return field instanceof CheckboxField ? field : void 0;
|
|
27241
27222
|
}
|
|
27242
27223
|
/**
|
|
27243
27224
|
* Get a radio button group by name.
|
|
@@ -27246,7 +27227,7 @@ var PDFForm = class PDFForm {
|
|
|
27246
27227
|
*/
|
|
27247
27228
|
getRadioGroup(name) {
|
|
27248
27229
|
const field = this.fieldsByName.get(name);
|
|
27249
|
-
return field
|
|
27230
|
+
return field instanceof RadioField ? field : void 0;
|
|
27250
27231
|
}
|
|
27251
27232
|
/**
|
|
27252
27233
|
* Get a dropdown (combo box) field by name.
|
|
@@ -27255,7 +27236,7 @@ var PDFForm = class PDFForm {
|
|
|
27255
27236
|
*/
|
|
27256
27237
|
getDropdown(name) {
|
|
27257
27238
|
const field = this.fieldsByName.get(name);
|
|
27258
|
-
return field
|
|
27239
|
+
return field instanceof DropdownField ? field : void 0;
|
|
27259
27240
|
}
|
|
27260
27241
|
/**
|
|
27261
27242
|
* Get a list box field by name.
|
|
@@ -27264,7 +27245,7 @@ var PDFForm = class PDFForm {
|
|
|
27264
27245
|
*/
|
|
27265
27246
|
getListBox(name) {
|
|
27266
27247
|
const field = this.fieldsByName.get(name);
|
|
27267
|
-
return field
|
|
27248
|
+
return field instanceof ListBoxField ? field : void 0;
|
|
27268
27249
|
}
|
|
27269
27250
|
/**
|
|
27270
27251
|
* Get a signature field by name.
|
|
@@ -27273,7 +27254,7 @@ var PDFForm = class PDFForm {
|
|
|
27273
27254
|
*/
|
|
27274
27255
|
getSignatureField(name) {
|
|
27275
27256
|
const field = this.fieldsByName.get(name);
|
|
27276
|
-
return field
|
|
27257
|
+
return field instanceof SignatureField ? field : void 0;
|
|
27277
27258
|
}
|
|
27278
27259
|
/**
|
|
27279
27260
|
* Get a button field by name.
|
|
@@ -27282,7 +27263,7 @@ var PDFForm = class PDFForm {
|
|
|
27282
27263
|
*/
|
|
27283
27264
|
getButton(name) {
|
|
27284
27265
|
const field = this.fieldsByName.get(name);
|
|
27285
|
-
return field
|
|
27266
|
+
return field instanceof ButtonField ? field : void 0;
|
|
27286
27267
|
}
|
|
27287
27268
|
/**
|
|
27288
27269
|
* Check if a field exists.
|
|
@@ -27294,43 +27275,43 @@ var PDFForm = class PDFForm {
|
|
|
27294
27275
|
* Get all text fields.
|
|
27295
27276
|
*/
|
|
27296
27277
|
getTextFields() {
|
|
27297
|
-
return this.allFields.filter((f) => f
|
|
27278
|
+
return this.allFields.filter((f) => f instanceof TextField);
|
|
27298
27279
|
}
|
|
27299
27280
|
/**
|
|
27300
27281
|
* Get all checkboxes.
|
|
27301
27282
|
*/
|
|
27302
27283
|
getCheckboxes() {
|
|
27303
|
-
return this.allFields.filter((f) => f
|
|
27284
|
+
return this.allFields.filter((f) => f instanceof CheckboxField);
|
|
27304
27285
|
}
|
|
27305
27286
|
/**
|
|
27306
27287
|
* Get all radio button groups.
|
|
27307
27288
|
*/
|
|
27308
27289
|
getRadioGroups() {
|
|
27309
|
-
return this.allFields.filter((f) => f
|
|
27290
|
+
return this.allFields.filter((f) => f instanceof RadioField);
|
|
27310
27291
|
}
|
|
27311
27292
|
/**
|
|
27312
27293
|
* Get all dropdowns.
|
|
27313
27294
|
*/
|
|
27314
27295
|
getDropdowns() {
|
|
27315
|
-
return this.allFields.filter((f) => f
|
|
27296
|
+
return this.allFields.filter((f) => f instanceof DropdownField);
|
|
27316
27297
|
}
|
|
27317
27298
|
/**
|
|
27318
27299
|
* Get all list boxes.
|
|
27319
27300
|
*/
|
|
27320
27301
|
getListBoxes() {
|
|
27321
|
-
return this.allFields.filter((f) => f
|
|
27302
|
+
return this.allFields.filter((f) => f instanceof ListBoxField);
|
|
27322
27303
|
}
|
|
27323
27304
|
/**
|
|
27324
27305
|
* Get all signature fields.
|
|
27325
27306
|
*/
|
|
27326
27307
|
getSignatureFields() {
|
|
27327
|
-
return this.allFields.filter((f) => f
|
|
27308
|
+
return this.allFields.filter((f) => f instanceof SignatureField);
|
|
27328
27309
|
}
|
|
27329
27310
|
/**
|
|
27330
27311
|
* Get all buttons.
|
|
27331
27312
|
*/
|
|
27332
27313
|
getButtons() {
|
|
27333
|
-
return this.allFields.filter((f) => f
|
|
27314
|
+
return this.allFields.filter((f) => f instanceof ButtonField);
|
|
27334
27315
|
}
|
|
27335
27316
|
/**
|
|
27336
27317
|
* Create a new signature field.
|
|
@@ -27627,6 +27608,69 @@ var PDFForm = class PDFForm {
|
|
|
27627
27608
|
return field;
|
|
27628
27609
|
}
|
|
27629
27610
|
/**
|
|
27611
|
+
* Remove a form field from the document.
|
|
27612
|
+
*
|
|
27613
|
+
* This removes the field from the AcroForm and all its widget annotations
|
|
27614
|
+
* from their respective pages.
|
|
27615
|
+
*
|
|
27616
|
+
* @param fieldOrName - The field instance or field name to remove
|
|
27617
|
+
* @returns true if the field was found and removed, false otherwise
|
|
27618
|
+
*
|
|
27619
|
+
* @example
|
|
27620
|
+
* ```typescript
|
|
27621
|
+
* // Remove by field instance
|
|
27622
|
+
* const nameField = form.getTextField("name");
|
|
27623
|
+
* form.removeField(nameField);
|
|
27624
|
+
*
|
|
27625
|
+
* // Remove by name
|
|
27626
|
+
* form.removeField("email");
|
|
27627
|
+
* ```
|
|
27628
|
+
*/
|
|
27629
|
+
removeField(fieldOrName) {
|
|
27630
|
+
const field = typeof fieldOrName === "string" ? this.fieldsByName.get(fieldOrName) : fieldOrName;
|
|
27631
|
+
if (!field) return false;
|
|
27632
|
+
const fieldRef = field.getRef();
|
|
27633
|
+
if (!fieldRef) return false;
|
|
27634
|
+
this.removeWidgetsFromPages(field);
|
|
27635
|
+
const removed = this._acroForm.removeField(fieldRef);
|
|
27636
|
+
if (removed) {
|
|
27637
|
+
this.allFields = this.allFields.filter((f) => f !== field);
|
|
27638
|
+
this.fieldsByName.delete(field.name);
|
|
27639
|
+
}
|
|
27640
|
+
return removed;
|
|
27641
|
+
}
|
|
27642
|
+
/**
|
|
27643
|
+
* Remove all widgets of a field from their respective pages.
|
|
27644
|
+
*/
|
|
27645
|
+
removeWidgetsFromPages(field) {
|
|
27646
|
+
const widgets = field.getWidgets();
|
|
27647
|
+
const pageRefs = this._ctx.pages.getPages();
|
|
27648
|
+
const widgetRefKeys = /* @__PURE__ */ new Set();
|
|
27649
|
+
for (const widget of widgets) if (widget.ref) widgetRefKeys.add(`${widget.ref.objectNumber} ${widget.ref.generation}`);
|
|
27650
|
+
if (widgetRefKeys.size === 0) return;
|
|
27651
|
+
for (const pageRef of pageRefs) {
|
|
27652
|
+
const pageDict = this._ctx.registry.resolve(pageRef);
|
|
27653
|
+
if (!(pageDict instanceof PdfDict)) continue;
|
|
27654
|
+
const annotsEntry = pageDict.get("Annots");
|
|
27655
|
+
if (!annotsEntry) continue;
|
|
27656
|
+
let annots = null;
|
|
27657
|
+
if (annotsEntry instanceof PdfArray) annots = annotsEntry;
|
|
27658
|
+
else if (annotsEntry instanceof PdfRef) {
|
|
27659
|
+
const resolved = this._ctx.registry.resolve(annotsEntry);
|
|
27660
|
+
if (resolved instanceof PdfArray) annots = resolved;
|
|
27661
|
+
}
|
|
27662
|
+
if (!annots) continue;
|
|
27663
|
+
for (let i = annots.length - 1; i >= 0; i--) {
|
|
27664
|
+
const item = annots.at(i);
|
|
27665
|
+
if (item instanceof PdfRef) {
|
|
27666
|
+
const key$1 = `${item.objectNumber} ${item.generation}`;
|
|
27667
|
+
if (widgetRefKeys.has(key$1)) annots.remove(i);
|
|
27668
|
+
}
|
|
27669
|
+
}
|
|
27670
|
+
if (annots.length === 0) pageDict.delete("Annots");
|
|
27671
|
+
}
|
|
27672
|
+
}
|
|
27673
|
+
/**
|
|
27630
27674
|
* Validate that a field name is unique.
|
|
27631
27675
|
*/
|
|
27632
27676
|
validateUniqueName(name) {
|
|
@@ -27696,7 +27740,7 @@ var PDFForm = class PDFForm {
|
|
|
27696
27740
|
* // result.skipped: ["nonexistent"]
|
|
27697
27741
|
* ```
|
|
27698
27742
|
*/
|
|
27699
|
-
|
|
27743
|
+
fill(values) {
|
|
27700
27744
|
const filled = [];
|
|
27701
27745
|
const skipped = [];
|
|
27702
27746
|
for (const [name, value] of Object.entries(values)) {
|
|
@@ -27705,7 +27749,7 @@ var PDFForm = class PDFForm {
|
|
|
27705
27749
|
skipped.push(name);
|
|
27706
27750
|
continue;
|
|
27707
27751
|
}
|
|
27708
|
-
|
|
27752
|
+
this.setFieldValue(field, value);
|
|
27709
27753
|
filled.push(name);
|
|
27710
27754
|
}
|
|
27711
27755
|
return {
|
|
@@ -27716,8 +27760,8 @@ var PDFForm = class PDFForm {
|
|
|
27716
27760
|
/**
|
|
27717
27761
|
* Reset all fields to their default values.
|
|
27718
27762
|
*/
|
|
27719
|
-
|
|
27720
|
-
for (const field of this.allFields) if (field instanceof TerminalField)
|
|
27763
|
+
resetAll() {
|
|
27764
|
+
for (const field of this.allFields) if (field instanceof TerminalField) field.resetValue();
|
|
27721
27765
|
}
|
|
27722
27766
|
/**
|
|
27723
27767
|
* Get form-level properties.
|
|
@@ -27762,8 +27806,8 @@ var PDFForm = class PDFForm {
|
|
|
27762
27806
|
* Call this if the form structure has been modified externally
|
|
27763
27807
|
* (e.g., fields added or removed via low-level API).
|
|
27764
27808
|
*/
|
|
27765
|
-
|
|
27766
|
-
const fields =
|
|
27809
|
+
reloadFields() {
|
|
27810
|
+
const fields = this._acroForm.getFields();
|
|
27767
27811
|
this.allFields = fields;
|
|
27768
27812
|
this.fieldsByName = new Map(fields.map((f) => [f.name, f]));
|
|
27769
27813
|
}
|
|
@@ -27773,8 +27817,8 @@ var PDFForm = class PDFForm {
|
|
|
27773
27817
|
* This regenerates the visual appearance of fields whose values have changed.
|
|
27774
27818
|
* Called automatically during `flatten()`.
|
|
27775
27819
|
*/
|
|
27776
|
-
|
|
27777
|
-
|
|
27820
|
+
updateAppearances() {
|
|
27821
|
+
this._acroForm.updateAppearances();
|
|
27778
27822
|
}
|
|
27779
27823
|
/**
|
|
27780
27824
|
* Flatten all form fields into static page content.
|
|
@@ -27795,8 +27839,8 @@ var PDFForm = class PDFForm {
|
|
|
27795
27839
|
* const bytes = await pdf.save();
|
|
27796
27840
|
* ```
|
|
27797
27841
|
*/
|
|
27798
|
-
|
|
27799
|
-
|
|
27842
|
+
flatten(options = {}) {
|
|
27843
|
+
this._acroForm.flatten(options);
|
|
27800
27844
|
this._ctx.catalog.removeAcroForm();
|
|
27801
27845
|
this.allFields = [];
|
|
27802
27846
|
this.fieldsByName.clear();
|
|
@@ -27820,39 +27864,49 @@ var PDFForm = class PDFForm {
|
|
|
27820
27864
|
/**
|
|
27821
27865
|
* Set a field's value with type checking.
|
|
27822
27866
|
*/
|
|
27823
|
-
|
|
27824
|
-
|
|
27825
|
-
|
|
27826
|
-
|
|
27827
|
-
|
|
27828
|
-
|
|
27829
|
-
|
|
27830
|
-
|
|
27831
|
-
|
|
27832
|
-
else
|
|
27833
|
-
|
|
27834
|
-
|
|
27835
|
-
|
|
27836
|
-
|
|
27837
|
-
|
|
27838
|
-
|
|
27839
|
-
|
|
27840
|
-
|
|
27841
|
-
|
|
27842
|
-
|
|
27843
|
-
|
|
27844
|
-
|
|
27845
|
-
await field.setValue(value);
|
|
27846
|
-
break;
|
|
27847
|
-
case "signature":
|
|
27848
|
-
case "button": throw new Error(`Cannot set value on ${field.type} field "${field.name}"`);
|
|
27849
|
-
default: throw new Error(`Unknown field type for "${field.name}"`);
|
|
27867
|
+
setFieldValue(field, value) {
|
|
27868
|
+
if (field instanceof TextField) {
|
|
27869
|
+
if (typeof value !== "string") throw new TypeError(`Text field "${field.name}" requires string value, got ${typeof value}`);
|
|
27870
|
+
field.setValue(value);
|
|
27871
|
+
return;
|
|
27872
|
+
}
|
|
27873
|
+
if (field instanceof CheckboxField) {
|
|
27874
|
+
if (typeof value === "boolean") {
|
|
27875
|
+
if (value) field.check();
|
|
27876
|
+
else field.uncheck();
|
|
27877
|
+
return;
|
|
27878
|
+
}
|
|
27879
|
+
if (typeof value === "string") {
|
|
27880
|
+
field.setValue(value);
|
|
27881
|
+
return;
|
|
27882
|
+
}
|
|
27883
|
+
throw new TypeError(`Checkbox "${field.name}" requires boolean or string value`);
|
|
27884
|
+
}
|
|
27885
|
+
if (field instanceof RadioField) {
|
|
27886
|
+
if (typeof value !== "string" && value !== null) throw new TypeError(`Radio field "${field.name}" requires string or null value`);
|
|
27887
|
+
field.setValue(value);
|
|
27888
|
+
return;
|
|
27850
27889
|
}
|
|
27890
|
+
if (field instanceof DropdownField) {
|
|
27891
|
+
if (typeof value !== "string") throw new TypeError(`Dropdown "${field.name}" requires string value`);
|
|
27892
|
+
field.setValue(value);
|
|
27893
|
+
return;
|
|
27894
|
+
}
|
|
27895
|
+
if (field instanceof ListBoxField) {
|
|
27896
|
+
if (!Array.isArray(value)) throw new TypeError(`Listbox "${field.name}" requires string[] value`);
|
|
27897
|
+
field.setValue(value);
|
|
27898
|
+
return;
|
|
27899
|
+
}
|
|
27900
|
+
if (field instanceof SignatureField || field instanceof ButtonField) throw new Error(`Cannot set value on ${field.type} field "${field.name}"`);
|
|
27901
|
+
throw new Error(`Unknown field type for "${field.name}"`);
|
|
27851
27902
|
}
|
|
27852
27903
|
};
|
|
27853
27904
|
|
|
27854
27905
|
//#endregion
|
|
27855
27906
|
//#region src/annotations/types.ts
|
|
27907
|
+
const isAnnotationSubtype = (subtype) => {
|
|
27908
|
+
return subtype === "Text" || subtype === "Link" || subtype === "FreeText" || subtype === "Line" || subtype === "Square" || subtype === "Circle" || subtype === "Polygon" || subtype === "PolyLine" || subtype === "Highlight" || subtype === "Underline" || subtype === "Squiggly" || subtype === "StrikeOut" || subtype === "Stamp" || subtype === "Caret" || subtype === "Ink" || subtype === "Popup" || subtype === "FileAttachment" || subtype === "Widget";
|
|
27909
|
+
};
|
|
27856
27910
|
/**
|
|
27857
27911
|
* Annotation flags (PDF spec Table 165).
|
|
27858
27912
|
*/
|
|
@@ -27879,6 +27933,15 @@ let AnnotationFlags = /* @__PURE__ */ function(AnnotationFlags$1) {
|
|
|
27879
27933
|
AnnotationFlags$1[AnnotationFlags$1["LockedContents"] = 512] = "LockedContents";
|
|
27880
27934
|
return AnnotationFlags$1;
|
|
27881
27935
|
}({});
|
|
27936
|
+
const isTextAnnotationIcon = (icon) => {
|
|
27937
|
+
return icon === "Comment" || icon === "Key" || icon === "Note" || icon === "Help" || icon === "NewParagraph" || icon === "Paragraph" || icon === "Insert";
|
|
27938
|
+
};
|
|
27939
|
+
const isFileAttachmentIcon = (icon) => {
|
|
27940
|
+
return icon === "Graph" || icon === "Paperclip" || icon === "PushPin" || icon === "Tag";
|
|
27941
|
+
};
|
|
27942
|
+
const isDestinationType = (type) => {
|
|
27943
|
+
return type === "Fit" || type === "FitH" || type === "FitV" || type === "FitB" || type === "FitBH" || type === "FitBV" || type === "XYZ" || type === "FitR";
|
|
27944
|
+
};
|
|
27882
27945
|
|
|
27883
27946
|
//#endregion
|
|
27884
27947
|
//#region src/annotations/base.ts
|
|
@@ -27923,7 +27986,8 @@ var PDFAnnotation = class {
|
|
|
27923
27986
|
* Annotation subtype (e.g., "Text", "Highlight", "Link").
|
|
27924
27987
|
*/
|
|
27925
27988
|
get type() {
|
|
27926
|
-
|
|
27989
|
+
const subtype = this.dict.getName("Subtype")?.value;
|
|
27990
|
+
return isAnnotationSubtype(subtype) ? subtype : "Text";
|
|
27927
27991
|
}
|
|
27928
27992
|
/**
|
|
27929
27993
|
* Annotation rectangle in page coordinates.
|
|
@@ -27936,15 +28000,12 @@ var PDFAnnotation = class {
|
|
|
27936
28000
|
width: 0,
|
|
27937
28001
|
height: 0
|
|
27938
28002
|
};
|
|
27939
|
-
const x1 = arr.
|
|
27940
|
-
const y1 = arr.at(1)?.value ?? 0;
|
|
27941
|
-
const x2 = arr.at(2)?.value ?? 0;
|
|
27942
|
-
const y2 = arr.at(3)?.value ?? 0;
|
|
28003
|
+
const [x1, y1, x2, y2] = arr.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
|
|
27943
28004
|
return {
|
|
27944
|
-
x: Math.min(x1, x2),
|
|
27945
|
-
y: Math.min(y1, y2),
|
|
27946
|
-
width: Math.abs(x2 - x1),
|
|
27947
|
-
height: Math.abs(y2 - y1)
|
|
28005
|
+
x: Math.min(x1 ?? 0, x2 ?? 0),
|
|
28006
|
+
y: Math.min(y1 ?? 0, y2 ?? 0),
|
|
28007
|
+
width: Math.abs((x2 ?? 0) - (x1 ?? 0)),
|
|
28008
|
+
height: Math.abs((y2 ?? 0) - (y1 ?? 0))
|
|
27948
28009
|
};
|
|
27949
28010
|
}
|
|
27950
28011
|
/**
|
|
@@ -28061,7 +28122,7 @@ var PDFAnnotation = class {
|
|
|
28061
28122
|
*/
|
|
28062
28123
|
setColor(color) {
|
|
28063
28124
|
const components = colorToArray(color);
|
|
28064
|
-
this.dict.set("C", new PdfArray(components.map(PdfNumber.of)));
|
|
28125
|
+
this.dict.set("C", new PdfArray(components.map((n) => PdfNumber.of(n))));
|
|
28065
28126
|
this.markModified();
|
|
28066
28127
|
}
|
|
28067
28128
|
/**
|
|
@@ -28091,7 +28152,7 @@ var PDFAnnotation = class {
|
|
|
28091
28152
|
const bs = new PdfDict();
|
|
28092
28153
|
bs.set("W", PdfNumber.of(style.width ?? 1));
|
|
28093
28154
|
bs.set("S", PdfName.of(BORDER_STYLE_REVERSE_MAP[style.style ?? "solid"]));
|
|
28094
|
-
if (style.dashArray && style.dashArray.length > 0) bs.set("D", new PdfArray(style.dashArray.map(PdfNumber.of)));
|
|
28155
|
+
if (style.dashArray && style.dashArray.length > 0) bs.set("D", new PdfArray(style.dashArray.map((n) => PdfNumber.of(n))));
|
|
28095
28156
|
this.dict.set("BS", bs);
|
|
28096
28157
|
this.markModified();
|
|
28097
28158
|
}
|
|
@@ -28106,19 +28167,19 @@ var PDFAnnotation = class {
|
|
|
28106
28167
|
/**
|
|
28107
28168
|
* Get the normal appearance stream.
|
|
28108
28169
|
*/
|
|
28109
|
-
|
|
28170
|
+
getNormalAppearance() {
|
|
28110
28171
|
return this.getAppearance("N");
|
|
28111
28172
|
}
|
|
28112
28173
|
/**
|
|
28113
28174
|
* Get the rollover appearance stream.
|
|
28114
28175
|
*/
|
|
28115
|
-
|
|
28176
|
+
getRolloverAppearance() {
|
|
28116
28177
|
return this.getAppearance("R");
|
|
28117
28178
|
}
|
|
28118
28179
|
/**
|
|
28119
28180
|
* Get the down appearance stream.
|
|
28120
28181
|
*/
|
|
28121
|
-
|
|
28182
|
+
getDownAppearance() {
|
|
28122
28183
|
return this.getAppearance("D");
|
|
28123
28184
|
}
|
|
28124
28185
|
/**
|
|
@@ -28142,13 +28203,13 @@ var PDFAnnotation = class {
|
|
|
28142
28203
|
/**
|
|
28143
28204
|
* Get an appearance stream by type.
|
|
28144
28205
|
*/
|
|
28145
|
-
|
|
28206
|
+
getAppearance(type) {
|
|
28146
28207
|
const ap = this.dict.getDict("AP");
|
|
28147
28208
|
if (!ap) return null;
|
|
28148
|
-
|
|
28209
|
+
let entry = ap.get(type);
|
|
28149
28210
|
if (!entry) return null;
|
|
28150
|
-
|
|
28151
|
-
if (
|
|
28211
|
+
if (entry instanceof PdfRef) entry = this.registry.resolve(entry) ?? void 0;
|
|
28212
|
+
if (entry instanceof PdfStream) return entry;
|
|
28152
28213
|
return null;
|
|
28153
28214
|
}
|
|
28154
28215
|
/**
|
|
@@ -28326,15 +28387,15 @@ var PDFMarkupAnnotation = class extends PDFAnnotation {
|
|
|
28326
28387
|
/**
|
|
28327
28388
|
* Get the associated popup annotation, if any.
|
|
28328
28389
|
*/
|
|
28329
|
-
|
|
28390
|
+
getPopup() {
|
|
28330
28391
|
if (this._popup !== void 0) return this._popup;
|
|
28331
28392
|
const popupRef = this.popupRef;
|
|
28332
28393
|
if (!popupRef) {
|
|
28333
28394
|
this._popup = null;
|
|
28334
28395
|
return null;
|
|
28335
28396
|
}
|
|
28336
|
-
const popupDict =
|
|
28337
|
-
if (popupDict
|
|
28397
|
+
const popupDict = this.registry.resolve(popupRef);
|
|
28398
|
+
if (popupDict instanceof PdfDict) {
|
|
28338
28399
|
this._popup = new PDFPopupAnnotation(popupDict, popupRef, this.registry);
|
|
28339
28400
|
return this._popup;
|
|
28340
28401
|
}
|
|
@@ -28419,12 +28480,7 @@ var PDFFileAttachmentAnnotation = class extends PDFMarkupAnnotation {
|
|
|
28419
28480
|
get icon() {
|
|
28420
28481
|
const name = this.dict.getName("Name");
|
|
28421
28482
|
if (!name) return "PushPin";
|
|
28422
|
-
if (
|
|
28423
|
-
"Graph",
|
|
28424
|
-
"Paperclip",
|
|
28425
|
-
"PushPin",
|
|
28426
|
-
"Tag"
|
|
28427
|
-
].includes(name.value)) return name.value;
|
|
28483
|
+
if (isFileAttachmentIcon(name.value)) return name.value;
|
|
28428
28484
|
return "PushPin";
|
|
28429
28485
|
}
|
|
28430
28486
|
/**
|
|
@@ -28444,18 +28500,18 @@ var PDFFileAttachmentAnnotation = class extends PDFMarkupAnnotation {
|
|
|
28444
28500
|
/**
|
|
28445
28501
|
* Get the file specification dictionary.
|
|
28446
28502
|
*/
|
|
28447
|
-
|
|
28503
|
+
getFileSpec() {
|
|
28448
28504
|
const fsRef = this.fileSpecRef;
|
|
28449
28505
|
if (!fsRef) return this.dict.getDict("FS") ?? null;
|
|
28450
|
-
const resolved =
|
|
28506
|
+
const resolved = this.registry.resolve(fsRef);
|
|
28451
28507
|
if (resolved && resolved.type === "dict") return resolved;
|
|
28452
28508
|
return null;
|
|
28453
28509
|
}
|
|
28454
28510
|
/**
|
|
28455
28511
|
* Get the file name from the file specification.
|
|
28456
28512
|
*/
|
|
28457
|
-
|
|
28458
|
-
const fs =
|
|
28513
|
+
getFileName() {
|
|
28514
|
+
const fs = this.getFileSpec();
|
|
28459
28515
|
if (!fs) return null;
|
|
28460
28516
|
const uf = fs.getString("UF");
|
|
28461
28517
|
if (uf) return uf.asString();
|
|
@@ -28592,7 +28648,7 @@ var PDFInkAnnotation = class extends PDFMarkupAnnotation {
|
|
|
28592
28648
|
PdfNumber.of(maxY)
|
|
28593
28649
|
]),
|
|
28594
28650
|
InkList: inkList,
|
|
28595
|
-
C: new PdfArray(colorComponents.map(PdfNumber.of)),
|
|
28651
|
+
C: new PdfArray(colorComponents.map((n) => PdfNumber.of(n))),
|
|
28596
28652
|
F: PdfNumber.of(4)
|
|
28597
28653
|
});
|
|
28598
28654
|
if (options.width !== void 0) {
|
|
@@ -28614,7 +28670,7 @@ var PDFInkAnnotation = class extends PDFMarkupAnnotation {
|
|
|
28614
28670
|
const paths = [];
|
|
28615
28671
|
for (let i = 0; i < inkList.length; i++) {
|
|
28616
28672
|
const pathEntry = inkList.at(i);
|
|
28617
|
-
if (pathEntry && pathEntry
|
|
28673
|
+
if (pathEntry && pathEntry instanceof PdfArray) {
|
|
28618
28674
|
const pathArr = pathEntry;
|
|
28619
28675
|
const points = [];
|
|
28620
28676
|
for (let j = 0; j < pathArr.length; j += 2) {
|
|
@@ -28693,7 +28749,7 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
|
|
|
28693
28749
|
PdfNumber.of(end.x),
|
|
28694
28750
|
PdfNumber.of(end.y)
|
|
28695
28751
|
]),
|
|
28696
|
-
C: new PdfArray(colorComponents.map(PdfNumber.of)),
|
|
28752
|
+
C: new PdfArray(colorComponents.map((n) => PdfNumber.of(n))),
|
|
28697
28753
|
F: PdfNumber.of(4)
|
|
28698
28754
|
});
|
|
28699
28755
|
if (options.width !== void 0) {
|
|
@@ -28705,7 +28761,7 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
|
|
|
28705
28761
|
if (options.startStyle || options.endStyle) annotDict.set("LE", new PdfArray([PdfName.of(options.startStyle ?? "None"), PdfName.of(options.endStyle ?? "None")]));
|
|
28706
28762
|
if (options.interiorColor) {
|
|
28707
28763
|
const icComponents = colorToArray(options.interiorColor);
|
|
28708
|
-
annotDict.set("IC", new PdfArray(icComponents.map(PdfNumber.of)));
|
|
28764
|
+
annotDict.set("IC", new PdfArray(icComponents.map((n) => PdfNumber.of(n))));
|
|
28709
28765
|
}
|
|
28710
28766
|
if (options.contents) annotDict.set("Contents", PdfString.fromString(options.contents));
|
|
28711
28767
|
return annotDict;
|
|
@@ -28725,14 +28781,15 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
|
|
|
28725
28781
|
y: 0
|
|
28726
28782
|
}
|
|
28727
28783
|
};
|
|
28784
|
+
const [x1, y1, x2, y2] = l.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
|
|
28728
28785
|
return {
|
|
28729
28786
|
start: {
|
|
28730
|
-
x:
|
|
28731
|
-
y:
|
|
28787
|
+
x: x1 ?? 0,
|
|
28788
|
+
y: y1 ?? 0
|
|
28732
28789
|
},
|
|
28733
28790
|
end: {
|
|
28734
|
-
x:
|
|
28735
|
-
y:
|
|
28791
|
+
x: x2 ?? 0,
|
|
28792
|
+
y: y2 ?? 0
|
|
28736
28793
|
}
|
|
28737
28794
|
};
|
|
28738
28795
|
}
|
|
@@ -28772,7 +28829,8 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
|
|
|
28772
28829
|
get lineEndingStyles() {
|
|
28773
28830
|
const le = this.dict.getArray("LE");
|
|
28774
28831
|
if (!le || le.length < 2) return ["None", "None"];
|
|
28775
|
-
|
|
28832
|
+
const [startStyle, endStyle] = le.toArray().map((item) => item instanceof PdfName ? item.value : "None");
|
|
28833
|
+
return [startStyle ?? "None", endStyle ?? "None"];
|
|
28776
28834
|
}
|
|
28777
28835
|
/**
|
|
28778
28836
|
* Set the line ending styles.
|
|
@@ -28792,7 +28850,7 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
|
|
|
28792
28850
|
*/
|
|
28793
28851
|
setInteriorColor(color) {
|
|
28794
28852
|
const components = colorToArray(color);
|
|
28795
|
-
this.dict.set("IC", new PdfArray(components.map(PdfNumber.of)));
|
|
28853
|
+
this.dict.set("IC", new PdfArray(components.map((n) => PdfNumber.of(n))));
|
|
28796
28854
|
this.markModified();
|
|
28797
28855
|
}
|
|
28798
28856
|
/**
|
|
@@ -28862,7 +28920,7 @@ var PDFLinkAnnotation = class extends PDFAnnotation {
|
|
|
28862
28920
|
}
|
|
28863
28921
|
if (options.borderColor) {
|
|
28864
28922
|
const components = colorToArray(options.borderColor);
|
|
28865
|
-
annotDict.set("C", new PdfArray(components.map(PdfNumber.of)));
|
|
28923
|
+
annotDict.set("C", new PdfArray(components.map((n) => PdfNumber.of(n))));
|
|
28866
28924
|
}
|
|
28867
28925
|
if (options.uri) {
|
|
28868
28926
|
const action = PdfDict.of({
|
|
@@ -28917,7 +28975,7 @@ var PDFLinkAnnotation = class extends PDFAnnotation {
|
|
|
28917
28975
|
/**
|
|
28918
28976
|
* Get the parsed link action.
|
|
28919
28977
|
*/
|
|
28920
|
-
|
|
28978
|
+
getAction() {
|
|
28921
28979
|
const uri = this.uri;
|
|
28922
28980
|
if (uri) return {
|
|
28923
28981
|
type: "uri",
|
|
@@ -28960,8 +29018,8 @@ var PDFLinkAnnotation = class extends PDFAnnotation {
|
|
|
28960
29018
|
* Parse a destination value.
|
|
28961
29019
|
*/
|
|
28962
29020
|
parseDestination(dest) {
|
|
28963
|
-
if (Array.isArray(dest) || dest
|
|
28964
|
-
const arr = dest;
|
|
29021
|
+
if (Array.isArray(dest) || dest instanceof PdfArray) {
|
|
29022
|
+
const arr = dest instanceof PdfArray ? dest : new PdfArray(dest);
|
|
28965
29023
|
if (arr.length < 2) return null;
|
|
28966
29024
|
const pageEntry = arr.at(0);
|
|
28967
29025
|
let pageNum = 0;
|
|
@@ -28972,7 +29030,7 @@ var PDFLinkAnnotation = class extends PDFAnnotation {
|
|
|
28972
29030
|
const typeName = typeEntry instanceof PdfName ? typeEntry.value : "Fit";
|
|
28973
29031
|
const result = {
|
|
28974
29032
|
page: pageRef ?? pageNum,
|
|
28975
|
-
type: typeName
|
|
29033
|
+
type: isDestinationType(typeName) ? typeName : "Fit"
|
|
28976
29034
|
};
|
|
28977
29035
|
switch (typeName) {
|
|
28978
29036
|
case "XYZ": {
|
|
@@ -29082,7 +29140,7 @@ var PDFPolygonAnnotation = class extends PDFPolyAnnotation {
|
|
|
29082
29140
|
*/
|
|
29083
29141
|
setInteriorColor(color) {
|
|
29084
29142
|
const components = colorToArray(color);
|
|
29085
|
-
this.dict.set("IC", new PdfArray(components.map(PdfNumber.of)));
|
|
29143
|
+
this.dict.set("IC", new PdfArray(components.map((n) => PdfNumber.of(n))));
|
|
29086
29144
|
this.markModified();
|
|
29087
29145
|
}
|
|
29088
29146
|
/**
|
|
@@ -29103,7 +29161,8 @@ var PDFPolylineAnnotation = class extends PDFPolyAnnotation {
|
|
|
29103
29161
|
get lineEndingStyles() {
|
|
29104
29162
|
const le = this.dict.getArray("LE");
|
|
29105
29163
|
if (!le || le.length < 2) return ["None", "None"];
|
|
29106
|
-
|
|
29164
|
+
const [startStyle, endStyle] = le.toArray().map((item) => item instanceof PdfName ? item.value : "None");
|
|
29165
|
+
return [startStyle ?? "None", endStyle ?? "None"];
|
|
29107
29166
|
}
|
|
29108
29167
|
/**
|
|
29109
29168
|
* Set the line ending styles.
|
|
@@ -29146,7 +29205,7 @@ var PDFShapeAnnotation = class extends PDFMarkupAnnotation {
|
|
|
29146
29205
|
*/
|
|
29147
29206
|
setInteriorColor(color) {
|
|
29148
29207
|
const components = colorToArray(color);
|
|
29149
|
-
this.dict.set("IC", new PdfArray(components.map(PdfNumber.of)));
|
|
29208
|
+
this.dict.set("IC", new PdfArray(components.map((n) => PdfNumber.of(n))));
|
|
29150
29209
|
this.markModified();
|
|
29151
29210
|
}
|
|
29152
29211
|
/**
|
|
@@ -29156,11 +29215,12 @@ var PDFShapeAnnotation = class extends PDFMarkupAnnotation {
|
|
|
29156
29215
|
get rectDifference() {
|
|
29157
29216
|
const rd = this.dict.getArray("RD");
|
|
29158
29217
|
if (!rd || rd.length < 4) return null;
|
|
29218
|
+
const [x1, y1, x2, y2] = rd.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
|
|
29159
29219
|
return [
|
|
29160
|
-
|
|
29161
|
-
|
|
29162
|
-
|
|
29163
|
-
|
|
29220
|
+
x1 ?? 0,
|
|
29221
|
+
y1 ?? 0,
|
|
29222
|
+
x2 ?? 0,
|
|
29223
|
+
y2 ?? 0
|
|
29164
29224
|
];
|
|
29165
29225
|
}
|
|
29166
29226
|
/**
|
|
@@ -29198,7 +29258,7 @@ var PDFSquareAnnotation = class extends PDFShapeAnnotation {
|
|
|
29198
29258
|
Type: PdfName.of("Annot"),
|
|
29199
29259
|
Subtype: PdfName.of("Square"),
|
|
29200
29260
|
Rect: new PdfArray(rectToArray(rect)),
|
|
29201
|
-
C: new PdfArray(colorComponents.map(PdfNumber.of)),
|
|
29261
|
+
C: new PdfArray(colorComponents.map((n) => PdfNumber.of(n))),
|
|
29202
29262
|
F: PdfNumber.of(4)
|
|
29203
29263
|
});
|
|
29204
29264
|
if (options.borderWidth !== void 0) {
|
|
@@ -29209,7 +29269,7 @@ var PDFSquareAnnotation = class extends PDFShapeAnnotation {
|
|
|
29209
29269
|
}
|
|
29210
29270
|
if (options.fillColor) {
|
|
29211
29271
|
const icComponents = colorToArray(options.fillColor);
|
|
29212
|
-
annotDict.set("IC", new PdfArray(icComponents.map(PdfNumber.of)));
|
|
29272
|
+
annotDict.set("IC", new PdfArray(icComponents.map((n) => PdfNumber.of(n))));
|
|
29213
29273
|
}
|
|
29214
29274
|
if (options.contents) annotDict.set("Contents", PdfString.fromString(options.contents));
|
|
29215
29275
|
return annotDict;
|
|
@@ -29229,7 +29289,7 @@ var PDFCircleAnnotation = class extends PDFShapeAnnotation {
|
|
|
29229
29289
|
Type: PdfName.of("Annot"),
|
|
29230
29290
|
Subtype: PdfName.of("Circle"),
|
|
29231
29291
|
Rect: new PdfArray(rectToArray(rect)),
|
|
29232
|
-
C: new PdfArray(colorComponents.map(PdfNumber.of)),
|
|
29292
|
+
C: new PdfArray(colorComponents.map((n) => PdfNumber.of(n))),
|
|
29233
29293
|
F: PdfNumber.of(4)
|
|
29234
29294
|
});
|
|
29235
29295
|
if (options.borderWidth !== void 0) {
|
|
@@ -29240,7 +29300,7 @@ var PDFCircleAnnotation = class extends PDFShapeAnnotation {
|
|
|
29240
29300
|
}
|
|
29241
29301
|
if (options.fillColor) {
|
|
29242
29302
|
const icComponents = colorToArray(options.fillColor);
|
|
29243
|
-
annotDict.set("IC", new PdfArray(icComponents.map(PdfNumber.of)));
|
|
29303
|
+
annotDict.set("IC", new PdfArray(icComponents.map((n) => PdfNumber.of(n))));
|
|
29244
29304
|
}
|
|
29245
29305
|
if (options.contents) annotDict.set("Contents", PdfString.fromString(options.contents));
|
|
29246
29306
|
return annotDict;
|
|
@@ -29326,6 +29386,12 @@ var PDFStampAnnotation = class extends PDFMarkupAnnotation {
|
|
|
29326
29386
|
*
|
|
29327
29387
|
* PDF Reference: Section 12.5.6.4 "Text Annotations"
|
|
29328
29388
|
*/
|
|
29389
|
+
const isTextAnnotationState = (state) => {
|
|
29390
|
+
return state === "Marked" || state === "Unmarked" || state === "Accepted" || state === "Rejected" || state === "Cancelled" || state === "Completed" || state === "None";
|
|
29391
|
+
};
|
|
29392
|
+
const isTextAnnotationStateModel = (model) => {
|
|
29393
|
+
return model === "Marked" || model === "Review";
|
|
29394
|
+
};
|
|
29329
29395
|
/**
|
|
29330
29396
|
* Text annotation - sticky note/comment.
|
|
29331
29397
|
*/
|
|
@@ -29340,7 +29406,7 @@ var PDFTextAnnotation = class extends PDFMarkupAnnotation {
|
|
|
29340
29406
|
Type: PdfName.of("Annot"),
|
|
29341
29407
|
Subtype: PdfName.of("Text"),
|
|
29342
29408
|
Rect: new PdfArray(rectToArray(rect)),
|
|
29343
|
-
C: new PdfArray(colorComponents.map(PdfNumber.of)),
|
|
29409
|
+
C: new PdfArray(colorComponents.map((n) => PdfNumber.of(n))),
|
|
29344
29410
|
F: PdfNumber.of(4)
|
|
29345
29411
|
});
|
|
29346
29412
|
if (options.contents) annotDict.set("Contents", PdfString.fromString(options.contents));
|
|
@@ -29368,15 +29434,7 @@ var PDFTextAnnotation = class extends PDFMarkupAnnotation {
|
|
|
29368
29434
|
get icon() {
|
|
29369
29435
|
const name = this.dict.getName("Name");
|
|
29370
29436
|
if (!name) return "Note";
|
|
29371
|
-
if (
|
|
29372
|
-
"Comment",
|
|
29373
|
-
"Key",
|
|
29374
|
-
"Note",
|
|
29375
|
-
"Help",
|
|
29376
|
-
"NewParagraph",
|
|
29377
|
-
"Paragraph",
|
|
29378
|
-
"Insert"
|
|
29379
|
-
].includes(name.value)) return name.value;
|
|
29437
|
+
if (isTextAnnotationIcon(name.value)) return name.value;
|
|
29380
29438
|
return "Note";
|
|
29381
29439
|
}
|
|
29382
29440
|
/**
|
|
@@ -29390,7 +29448,8 @@ var PDFTextAnnotation = class extends PDFMarkupAnnotation {
|
|
|
29390
29448
|
* State of the annotation (for review workflows).
|
|
29391
29449
|
*/
|
|
29392
29450
|
get state() {
|
|
29393
|
-
|
|
29451
|
+
const state = this.dict.getName("State")?.value;
|
|
29452
|
+
return isTextAnnotationState(state) ? state : null;
|
|
29394
29453
|
}
|
|
29395
29454
|
/**
|
|
29396
29455
|
* Set the annotation state.
|
|
@@ -29403,7 +29462,8 @@ var PDFTextAnnotation = class extends PDFMarkupAnnotation {
|
|
|
29403
29462
|
* State model for the annotation.
|
|
29404
29463
|
*/
|
|
29405
29464
|
get stateModel() {
|
|
29406
|
-
|
|
29465
|
+
const model = this.dict.getName("StateModel")?.value;
|
|
29466
|
+
return isTextAnnotationStateModel(model) ? model : null;
|
|
29407
29467
|
}
|
|
29408
29468
|
/**
|
|
29409
29469
|
* Set the state model.
|
|
@@ -29585,7 +29645,7 @@ function createTextMarkupDict(subtype, options) {
|
|
|
29585
29645
|
PdfNumber.of(maxY)
|
|
29586
29646
|
]),
|
|
29587
29647
|
QuadPoints: new PdfArray(flatQuadPoints),
|
|
29588
|
-
C: new PdfArray(colorComponents.map(PdfNumber.of)),
|
|
29648
|
+
C: new PdfArray(colorComponents.map((n) => PdfNumber.of(n))),
|
|
29589
29649
|
F: PdfNumber.of(4)
|
|
29590
29650
|
});
|
|
29591
29651
|
if (options.opacity !== void 0) annotDict.set("CA", PdfNumber.of(options.opacity));
|
|
@@ -29632,7 +29692,8 @@ var PDFUnknownAnnotation = class extends PDFAnnotation {};
|
|
|
29632
29692
|
* @returns The appropriate annotation class instance
|
|
29633
29693
|
*/
|
|
29634
29694
|
function createAnnotation(dict, ref, registry) {
|
|
29635
|
-
|
|
29695
|
+
const subtypeName = dict.getName("Subtype")?.value;
|
|
29696
|
+
switch (isAnnotationSubtype(subtypeName) ? subtypeName : "Text") {
|
|
29636
29697
|
case "Text": return new PDFTextAnnotation(dict, ref, registry);
|
|
29637
29698
|
case "Link": return new PDFLinkAnnotation(dict, ref, registry);
|
|
29638
29699
|
case "FreeText": return new PDFFreeTextAnnotation(dict, ref, registry);
|
|
@@ -29688,6 +29749,9 @@ function isPopupAnnotation(dict) {
|
|
|
29688
29749
|
* /CIDToGIDMap /Identity
|
|
29689
29750
|
* >>
|
|
29690
29751
|
*/
|
|
29752
|
+
const isCIDFontSubtype = (subtype) => {
|
|
29753
|
+
return subtype === "CIDFontType0" || subtype === "CIDFontType2";
|
|
29754
|
+
};
|
|
29691
29755
|
/**
|
|
29692
29756
|
* CIDFont handles CID-keyed fonts (descendants of Type0).
|
|
29693
29757
|
*/
|
|
@@ -29841,7 +29905,8 @@ function parseCIDWidths(wArray) {
|
|
|
29841
29905
|
* Parse a CIDFont from a PDF font dictionary.
|
|
29842
29906
|
*/
|
|
29843
29907
|
function parseCIDFont(dict, options = {}) {
|
|
29844
|
-
const
|
|
29908
|
+
const subtypeName = dict.getName("Subtype");
|
|
29909
|
+
const subtype = isCIDFontSubtype(subtypeName?.value) ? subtypeName.value : "CIDFontType2";
|
|
29845
29910
|
const baseFontName = dict.getName("BaseFont")?.value ?? "Unknown";
|
|
29846
29911
|
let cidSystemInfo = {
|
|
29847
29912
|
registry: "Adobe",
|
|
@@ -31812,7 +31877,7 @@ var TextExtractor = class {
|
|
|
31812
31877
|
* Process a single content stream operation.
|
|
31813
31878
|
*/
|
|
31814
31879
|
processOperation(op) {
|
|
31815
|
-
if (op
|
|
31880
|
+
if (isInlineImageOperation(op)) return;
|
|
31816
31881
|
const { operator, operands } = op;
|
|
31817
31882
|
switch (operator) {
|
|
31818
31883
|
case "q":
|
|
@@ -32981,11 +33046,11 @@ var PDFPage = class PDFPage {
|
|
|
32981
33046
|
* await page.drawField(paymentRadio, { x: 100, y: 520, width: 16, height: 16, option: "PayPal" });
|
|
32982
33047
|
* ```
|
|
32983
33048
|
*/
|
|
32984
|
-
|
|
33049
|
+
drawField(field, options) {
|
|
32985
33050
|
if (!this.ctx) throw new Error("Cannot draw field on page without context");
|
|
32986
33051
|
if (!(field instanceof TerminalField)) throw new Error(`Cannot draw non-terminal field "${field.name}"`);
|
|
32987
|
-
if (field
|
|
32988
|
-
if (field
|
|
33052
|
+
if (field instanceof SignatureField) throw new Error("Signature fields cannot be drawn with drawField. Use form.createSignatureField() which creates the widget automatically.");
|
|
33053
|
+
if (field instanceof RadioField) {
|
|
32989
33054
|
if (!options.option) throw new Error(`Radio group "${field.name}" requires option parameter in drawField`);
|
|
32990
33055
|
const availableOptions = field.getOptions();
|
|
32991
33056
|
const optArray = field.acroField().getArray("Opt");
|
|
@@ -32993,7 +33058,7 @@ var PDFPage = class PDFPage {
|
|
|
32993
33058
|
const optValues = [];
|
|
32994
33059
|
for (let i = 0; i < optArray.length; i++) {
|
|
32995
33060
|
const item = optArray.at(i);
|
|
32996
|
-
if (item
|
|
33061
|
+
if (item instanceof PdfString) optValues.push(item.asString());
|
|
32997
33062
|
}
|
|
32998
33063
|
if (!optValues.includes(options.option)) throw new Error(`Invalid option "${options.option}" for radio group "${field.name}". Available: ${optValues.join(", ")}`);
|
|
32999
33064
|
} else if (availableOptions.length > 0 && !availableOptions.includes(options.option)) throw new Error(`Invalid option "${options.option}" for radio group "${field.name}". Available: ${availableOptions.join(", ")}`);
|
|
@@ -33002,7 +33067,7 @@ var PDFPage = class PDFPage {
|
|
|
33002
33067
|
const widget = field.addWidget(widgetDict);
|
|
33003
33068
|
if (!widget.ref) throw new Error("Widget annotation must have a reference");
|
|
33004
33069
|
this.addAnnotationRef(widget.ref);
|
|
33005
|
-
|
|
33070
|
+
this.generateWidgetAppearance(field, widget, options);
|
|
33006
33071
|
}
|
|
33007
33072
|
/**
|
|
33008
33073
|
* Build a widget annotation dictionary for a field.
|
|
@@ -33051,11 +33116,11 @@ var PDFPage = class PDFPage {
|
|
|
33051
33116
|
});
|
|
33052
33117
|
widgetDict.set("BS", bs);
|
|
33053
33118
|
}
|
|
33054
|
-
if (field
|
|
33119
|
+
if (field instanceof RadioField && options.option) {
|
|
33055
33120
|
const currentValue = field.getValue();
|
|
33056
33121
|
widgetDict.set("AS", PdfName.of(currentValue === options.option ? options.option : "Off"));
|
|
33057
33122
|
}
|
|
33058
|
-
if (field
|
|
33123
|
+
if (field instanceof CheckboxField) {
|
|
33059
33124
|
const checkboxField = field;
|
|
33060
33125
|
const isChecked = checkboxField.isChecked();
|
|
33061
33126
|
const onValue = checkboxField.getOnValue();
|
|
@@ -33066,47 +33131,45 @@ var PDFPage = class PDFPage {
|
|
|
33066
33131
|
/**
|
|
33067
33132
|
* Generate appearance stream for a widget.
|
|
33068
33133
|
*/
|
|
33069
|
-
|
|
33134
|
+
generateWidgetAppearance(field, widget, options) {
|
|
33070
33135
|
if (!this.ctx) return;
|
|
33071
33136
|
const catalogDict = this.ctx.catalog.getDict();
|
|
33072
|
-
const acroForm =
|
|
33137
|
+
const acroForm = AcroForm.load(catalogDict, this.ctx.registry);
|
|
33073
33138
|
if (!acroForm) return;
|
|
33074
33139
|
const generator = new AppearanceGenerator(acroForm, this.ctx.registry);
|
|
33075
|
-
|
|
33076
|
-
|
|
33077
|
-
|
|
33078
|
-
|
|
33079
|
-
|
|
33080
|
-
|
|
33081
|
-
|
|
33082
|
-
|
|
33083
|
-
|
|
33084
|
-
|
|
33085
|
-
|
|
33086
|
-
|
|
33087
|
-
|
|
33088
|
-
|
|
33089
|
-
|
|
33090
|
-
|
|
33091
|
-
|
|
33092
|
-
|
|
33093
|
-
|
|
33094
|
-
|
|
33095
|
-
|
|
33096
|
-
|
|
33097
|
-
|
|
33098
|
-
|
|
33099
|
-
|
|
33100
|
-
|
|
33101
|
-
|
|
33102
|
-
|
|
33103
|
-
|
|
33104
|
-
|
|
33105
|
-
|
|
33106
|
-
|
|
33107
|
-
|
|
33108
|
-
break;
|
|
33109
|
-
}
|
|
33140
|
+
if (field instanceof TextField) {
|
|
33141
|
+
const textField = field;
|
|
33142
|
+
const stream = generator.generateTextAppearance(textField, widget);
|
|
33143
|
+
widget.setNormalAppearance(stream);
|
|
33144
|
+
return;
|
|
33145
|
+
}
|
|
33146
|
+
if (field instanceof CheckboxField) {
|
|
33147
|
+
const checkboxField = field;
|
|
33148
|
+
const onValue = checkboxField.getOnValue();
|
|
33149
|
+
const { on, off } = generator.generateCheckboxAppearance(checkboxField, widget, onValue);
|
|
33150
|
+
widget.setNormalAppearance(on, onValue);
|
|
33151
|
+
widget.setNormalAppearance(off, "Off");
|
|
33152
|
+
return;
|
|
33153
|
+
}
|
|
33154
|
+
if (field instanceof RadioField) {
|
|
33155
|
+
const radioField = field;
|
|
33156
|
+
if (!options.option) throw new Error("Radio field requires an option value");
|
|
33157
|
+
const { selected, off } = generator.generateRadioAppearance(radioField, widget, options.option);
|
|
33158
|
+
widget.setNormalAppearance(selected, options.option);
|
|
33159
|
+
widget.setNormalAppearance(off, "Off");
|
|
33160
|
+
return;
|
|
33161
|
+
}
|
|
33162
|
+
if (field instanceof DropdownField) {
|
|
33163
|
+
const dropdownField = field;
|
|
33164
|
+
const stream = generator.generateDropdownAppearance(dropdownField, widget);
|
|
33165
|
+
widget.setNormalAppearance(stream);
|
|
33166
|
+
return;
|
|
33167
|
+
}
|
|
33168
|
+
if (field instanceof ListBoxField) {
|
|
33169
|
+
const listboxField = field;
|
|
33170
|
+
const stream = generator.generateListBoxAppearance(listboxField, widget);
|
|
33171
|
+
widget.setNormalAppearance(stream);
|
|
33172
|
+
return;
|
|
33110
33173
|
}
|
|
33111
33174
|
}
|
|
33112
33175
|
/**
|
|
@@ -33467,13 +33530,13 @@ var PDFPage = class PDFPage {
|
|
|
33467
33530
|
*
|
|
33468
33531
|
* @example
|
|
33469
33532
|
* ```typescript
|
|
33470
|
-
* const annotations =
|
|
33533
|
+
* const annotations = page.getAnnotations();
|
|
33471
33534
|
* for (const annot of annotations) {
|
|
33472
33535
|
* console.log(annot.type, annot.contents);
|
|
33473
33536
|
* }
|
|
33474
33537
|
* ```
|
|
33475
33538
|
*/
|
|
33476
|
-
|
|
33539
|
+
getAnnotations() {
|
|
33477
33540
|
if (this._annotationCache) return this._annotationCache;
|
|
33478
33541
|
const annotations = [];
|
|
33479
33542
|
const annotsArray = this.dict.getArray("Annots");
|
|
@@ -33488,7 +33551,7 @@ var PDFPage = class PDFPage {
|
|
|
33488
33551
|
let annotRef = null;
|
|
33489
33552
|
if (entry instanceof PdfRef) {
|
|
33490
33553
|
annotRef = entry;
|
|
33491
|
-
const resolved =
|
|
33554
|
+
const resolved = this.ctx.resolve(entry);
|
|
33492
33555
|
if (resolved instanceof PdfDict) annotDict = resolved;
|
|
33493
33556
|
} else if (entry instanceof PdfDict) annotDict = entry;
|
|
33494
33557
|
if (!annotDict) continue;
|
|
@@ -33505,20 +33568,20 @@ var PDFPage = class PDFPage {
|
|
|
33505
33568
|
* Popups are typically accessed via their parent markup annotation
|
|
33506
33569
|
* using `annotation.getPopup()`, but this method allows direct access.
|
|
33507
33570
|
*/
|
|
33508
|
-
|
|
33571
|
+
getPopupAnnotations() {
|
|
33509
33572
|
const popups = [];
|
|
33510
33573
|
const annotsArray = this.dict.getArray("Annots");
|
|
33511
33574
|
if (!annotsArray || !this.ctx) return popups;
|
|
33512
33575
|
for (let i = 0; i < annotsArray.length; i++) {
|
|
33513
|
-
|
|
33576
|
+
let entry = annotsArray.at(i);
|
|
33514
33577
|
if (!entry) continue;
|
|
33515
33578
|
let annotDict = null;
|
|
33516
33579
|
let annotRef = null;
|
|
33517
33580
|
if (entry instanceof PdfRef) {
|
|
33518
33581
|
annotRef = entry;
|
|
33519
|
-
|
|
33520
|
-
|
|
33521
|
-
|
|
33582
|
+
entry = this.ctx.resolve(entry) ?? void 0;
|
|
33583
|
+
}
|
|
33584
|
+
if (entry instanceof PdfDict) annotDict = entry;
|
|
33522
33585
|
if (!annotDict || !isPopupAnnotation(annotDict)) continue;
|
|
33523
33586
|
popups.push(new PDFPopupAnnotation(annotDict, annotRef, this.ctx.registry));
|
|
33524
33587
|
}
|
|
@@ -33527,98 +33590,98 @@ var PDFPage = class PDFPage {
|
|
|
33527
33590
|
/**
|
|
33528
33591
|
* Get all highlight annotations on this page.
|
|
33529
33592
|
*/
|
|
33530
|
-
|
|
33531
|
-
return
|
|
33593
|
+
getHighlightAnnotations() {
|
|
33594
|
+
return this.getAnnotations().filter((a) => a.type === "Highlight");
|
|
33532
33595
|
}
|
|
33533
33596
|
/**
|
|
33534
33597
|
* Get all underline annotations on this page.
|
|
33535
33598
|
*/
|
|
33536
|
-
|
|
33537
|
-
return
|
|
33599
|
+
getUnderlineAnnotations() {
|
|
33600
|
+
return this.getAnnotations().filter((a) => a.type === "Underline");
|
|
33538
33601
|
}
|
|
33539
33602
|
/**
|
|
33540
33603
|
* Get all strikeout annotations on this page.
|
|
33541
33604
|
*/
|
|
33542
|
-
|
|
33543
|
-
return
|
|
33605
|
+
getStrikeOutAnnotations() {
|
|
33606
|
+
return this.getAnnotations().filter((a) => a.type === "StrikeOut");
|
|
33544
33607
|
}
|
|
33545
33608
|
/**
|
|
33546
33609
|
* Get all squiggly annotations on this page.
|
|
33547
33610
|
*/
|
|
33548
|
-
|
|
33549
|
-
return
|
|
33611
|
+
getSquigglyAnnotations() {
|
|
33612
|
+
return this.getAnnotations().filter((a) => a.type === "Squiggly");
|
|
33550
33613
|
}
|
|
33551
33614
|
/**
|
|
33552
33615
|
* Get all link annotations on this page.
|
|
33553
33616
|
*/
|
|
33554
|
-
|
|
33555
|
-
return
|
|
33617
|
+
getLinkAnnotations() {
|
|
33618
|
+
return this.getAnnotations().filter((a) => a.type === "Link");
|
|
33556
33619
|
}
|
|
33557
33620
|
/**
|
|
33558
33621
|
* Get all text annotations (sticky notes) on this page.
|
|
33559
33622
|
*/
|
|
33560
|
-
|
|
33561
|
-
return
|
|
33623
|
+
getTextAnnotations() {
|
|
33624
|
+
return this.getAnnotations().filter((a) => a.type === "Text");
|
|
33562
33625
|
}
|
|
33563
33626
|
/**
|
|
33564
33627
|
* Get all free text annotations on this page.
|
|
33565
33628
|
*/
|
|
33566
|
-
|
|
33567
|
-
return
|
|
33629
|
+
getFreeTextAnnotations() {
|
|
33630
|
+
return this.getAnnotations().filter((a) => a.type === "FreeText");
|
|
33568
33631
|
}
|
|
33569
33632
|
/**
|
|
33570
33633
|
* Get all line annotations on this page.
|
|
33571
33634
|
*/
|
|
33572
|
-
|
|
33573
|
-
return
|
|
33635
|
+
getLineAnnotations() {
|
|
33636
|
+
return this.getAnnotations().filter((a) => a.type === "Line");
|
|
33574
33637
|
}
|
|
33575
33638
|
/**
|
|
33576
33639
|
* Get all square annotations on this page.
|
|
33577
33640
|
*/
|
|
33578
|
-
|
|
33579
|
-
return
|
|
33641
|
+
getSquareAnnotations() {
|
|
33642
|
+
return this.getAnnotations().filter((a) => a.type === "Square");
|
|
33580
33643
|
}
|
|
33581
33644
|
/**
|
|
33582
33645
|
* Get all circle annotations on this page.
|
|
33583
33646
|
*/
|
|
33584
|
-
|
|
33585
|
-
return
|
|
33647
|
+
getCircleAnnotations() {
|
|
33648
|
+
return this.getAnnotations().filter((a) => a.type === "Circle");
|
|
33586
33649
|
}
|
|
33587
33650
|
/**
|
|
33588
33651
|
* Get all stamp annotations on this page.
|
|
33589
33652
|
*/
|
|
33590
|
-
|
|
33591
|
-
return
|
|
33653
|
+
getStampAnnotations() {
|
|
33654
|
+
return this.getAnnotations().filter((a) => a.type === "Stamp");
|
|
33592
33655
|
}
|
|
33593
33656
|
/**
|
|
33594
33657
|
* Get all ink annotations on this page.
|
|
33595
33658
|
*/
|
|
33596
|
-
|
|
33597
|
-
return
|
|
33659
|
+
getInkAnnotations() {
|
|
33660
|
+
return this.getAnnotations().filter((a) => a.type === "Ink");
|
|
33598
33661
|
}
|
|
33599
33662
|
/**
|
|
33600
33663
|
* Get all polygon annotations on this page.
|
|
33601
33664
|
*/
|
|
33602
|
-
|
|
33603
|
-
return
|
|
33665
|
+
getPolygonAnnotations() {
|
|
33666
|
+
return this.getAnnotations().filter((a) => a.type === "Polygon");
|
|
33604
33667
|
}
|
|
33605
33668
|
/**
|
|
33606
33669
|
* Get all polyline annotations on this page.
|
|
33607
33670
|
*/
|
|
33608
|
-
|
|
33609
|
-
return
|
|
33671
|
+
getPolylineAnnotations() {
|
|
33672
|
+
return this.getAnnotations().filter((a) => a.type === "PolyLine");
|
|
33610
33673
|
}
|
|
33611
33674
|
/**
|
|
33612
33675
|
* Get all caret annotations on this page.
|
|
33613
33676
|
*/
|
|
33614
|
-
|
|
33615
|
-
return
|
|
33677
|
+
getCaretAnnotations() {
|
|
33678
|
+
return this.getAnnotations().filter((a) => a.type === "Caret");
|
|
33616
33679
|
}
|
|
33617
33680
|
/**
|
|
33618
33681
|
* Get all file attachment annotations on this page.
|
|
33619
33682
|
*/
|
|
33620
|
-
|
|
33621
|
-
return
|
|
33683
|
+
getFileAttachmentAnnotations() {
|
|
33684
|
+
return this.getAnnotations().filter((a) => a.type === "FileAttachment");
|
|
33622
33685
|
}
|
|
33623
33686
|
/**
|
|
33624
33687
|
* Add a highlight annotation.
|
|
@@ -33818,11 +33881,11 @@ var PDFPage = class PDFPage {
|
|
|
33818
33881
|
*
|
|
33819
33882
|
* @example
|
|
33820
33883
|
* ```typescript
|
|
33821
|
-
* const highlights =
|
|
33822
|
-
*
|
|
33884
|
+
* const highlights = page.getHighlightAnnotations();
|
|
33885
|
+
* page.removeAnnotation(highlights[0]);
|
|
33823
33886
|
* ```
|
|
33824
33887
|
*/
|
|
33825
|
-
|
|
33888
|
+
removeAnnotation(annotation) {
|
|
33826
33889
|
if (!this.ctx) return;
|
|
33827
33890
|
const annots = this.dict.getArray("Annots");
|
|
33828
33891
|
if (!annots) return;
|
|
@@ -33851,17 +33914,17 @@ var PDFPage = class PDFPage {
|
|
|
33851
33914
|
* @example
|
|
33852
33915
|
* ```typescript
|
|
33853
33916
|
* // Remove all highlights
|
|
33854
|
-
*
|
|
33917
|
+
* page.removeAnnotations({ type: "Highlight" });
|
|
33855
33918
|
*
|
|
33856
33919
|
* // Remove all annotations
|
|
33857
|
-
*
|
|
33920
|
+
* page.removeAnnotations();
|
|
33858
33921
|
* ```
|
|
33859
33922
|
*/
|
|
33860
|
-
|
|
33861
|
-
const annotations =
|
|
33923
|
+
removeAnnotations(options) {
|
|
33924
|
+
const annotations = this.getAnnotations();
|
|
33862
33925
|
let toRemove = annotations;
|
|
33863
33926
|
if (options?.type) toRemove = annotations.filter((a) => a.type === options.type);
|
|
33864
|
-
for (const annotation of toRemove)
|
|
33927
|
+
for (const annotation of toRemove) this.removeAnnotation(annotation);
|
|
33865
33928
|
}
|
|
33866
33929
|
/**
|
|
33867
33930
|
* Add an annotation reference to the page's /Annots array.
|
|
@@ -34007,7 +34070,7 @@ var PDFPage = class PDFPage {
|
|
|
34007
34070
|
} else {
|
|
34008
34071
|
const contents = this.dict.get("Contents");
|
|
34009
34072
|
if (contents instanceof PdfArray) contents.push(newContent);
|
|
34010
|
-
else this.dict.set("Contents", new PdfArray([contents, newContent]));
|
|
34073
|
+
else if (contents !== void 0) this.dict.set("Contents", new PdfArray([contents, newContent]));
|
|
34011
34074
|
}
|
|
34012
34075
|
}
|
|
34013
34076
|
/**
|
|
@@ -34106,7 +34169,7 @@ var PDFPage = class PDFPage {
|
|
|
34106
34169
|
*
|
|
34107
34170
|
* @example
|
|
34108
34171
|
* ```typescript
|
|
34109
|
-
* const pageText =
|
|
34172
|
+
* const pageText = page.extractText();
|
|
34110
34173
|
* console.log(pageText.text); // Plain text
|
|
34111
34174
|
*
|
|
34112
34175
|
* // Access structured content
|
|
@@ -34115,9 +34178,9 @@ var PDFPage = class PDFPage {
|
|
|
34115
34178
|
* }
|
|
34116
34179
|
* ```
|
|
34117
34180
|
*/
|
|
34118
|
-
|
|
34119
|
-
const contentBytes =
|
|
34120
|
-
const lines = groupCharsIntoLines(new TextExtractor({ resolveFont:
|
|
34181
|
+
extractText(_options = {}) {
|
|
34182
|
+
const contentBytes = this.getContentBytes();
|
|
34183
|
+
const lines = groupCharsIntoLines(new TextExtractor({ resolveFont: this.createFontResolver() }).extract(contentBytes));
|
|
34121
34184
|
const text = getPlainText(lines);
|
|
34122
34185
|
return {
|
|
34123
34186
|
pageIndex: this.index,
|
|
@@ -34137,37 +34200,37 @@ var PDFPage = class PDFPage {
|
|
|
34137
34200
|
* @example
|
|
34138
34201
|
* ```typescript
|
|
34139
34202
|
* // String search
|
|
34140
|
-
* const matches =
|
|
34203
|
+
* const matches = page.findText("{{ name }}");
|
|
34141
34204
|
* for (const match of matches) {
|
|
34142
34205
|
* console.log(`Found at:`, match.bbox);
|
|
34143
34206
|
* }
|
|
34144
34207
|
*
|
|
34145
34208
|
* // Regex search
|
|
34146
|
-
* const placeholders =
|
|
34209
|
+
* const placeholders = page.findText(/\{\{\s*\w+\s*\}\}/g);
|
|
34147
34210
|
* ```
|
|
34148
34211
|
*/
|
|
34149
|
-
|
|
34150
|
-
return searchPage(
|
|
34212
|
+
findText(query, options = {}) {
|
|
34213
|
+
return searchPage(this.extractText(), query, options);
|
|
34151
34214
|
}
|
|
34152
34215
|
/**
|
|
34153
34216
|
* Get the concatenated content stream bytes.
|
|
34154
34217
|
*/
|
|
34155
|
-
|
|
34218
|
+
getContentBytes() {
|
|
34156
34219
|
const contents = this.dict.get("Contents");
|
|
34157
34220
|
if (!contents) return new Uint8Array(0);
|
|
34158
34221
|
if (contents instanceof PdfRef && this.ctx) {
|
|
34159
|
-
const stream =
|
|
34160
|
-
if (stream instanceof PdfStream) return
|
|
34222
|
+
const stream = this.ctx.resolve(contents);
|
|
34223
|
+
if (stream instanceof PdfStream) return stream.getDecodedData();
|
|
34161
34224
|
}
|
|
34162
|
-
if (contents instanceof PdfStream) return
|
|
34225
|
+
if (contents instanceof PdfStream) return contents.getDecodedData();
|
|
34163
34226
|
if (contents instanceof PdfArray) {
|
|
34164
34227
|
const chunks = [];
|
|
34165
34228
|
for (let i = 0; i < contents.length; i++) {
|
|
34166
34229
|
const item = contents.at(i);
|
|
34167
34230
|
if (item instanceof PdfRef && this.ctx) {
|
|
34168
|
-
const stream =
|
|
34169
|
-
if (stream instanceof PdfStream) chunks.push(
|
|
34170
|
-
} else if (item instanceof PdfStream) chunks.push(
|
|
34231
|
+
const stream = this.ctx.resolve(item);
|
|
34232
|
+
if (stream instanceof PdfStream) chunks.push(stream.getDecodedData());
|
|
34233
|
+
} else if (item instanceof PdfStream) chunks.push(item.getDecodedData());
|
|
34171
34234
|
}
|
|
34172
34235
|
return this.concatenateChunks(chunks);
|
|
34173
34236
|
}
|
|
@@ -34195,18 +34258,18 @@ var PDFPage = class PDFPage {
|
|
|
34195
34258
|
* PDF pages can inherit Resources from parent Pages nodes (see PDF spec 7.7.3.4).
|
|
34196
34259
|
* This method checks the page first, then walks up the Parent chain.
|
|
34197
34260
|
*/
|
|
34198
|
-
|
|
34261
|
+
resolveInheritedResources() {
|
|
34199
34262
|
if (!this.ctx) return null;
|
|
34200
34263
|
let currentDict = this.dict;
|
|
34201
34264
|
while (currentDict) {
|
|
34202
34265
|
const resourcesEntry = currentDict.get("Resources");
|
|
34203
34266
|
if (resourcesEntry instanceof PdfRef) {
|
|
34204
|
-
const resolved =
|
|
34267
|
+
const resolved = this.ctx.resolve(resourcesEntry);
|
|
34205
34268
|
if (resolved instanceof PdfDict) return resolved;
|
|
34206
34269
|
} else if (resourcesEntry instanceof PdfDict) return resourcesEntry;
|
|
34207
34270
|
const parentEntry = currentDict.get("Parent");
|
|
34208
34271
|
if (parentEntry instanceof PdfRef) {
|
|
34209
|
-
const parent =
|
|
34272
|
+
const parent = this.ctx.resolve(parentEntry);
|
|
34210
34273
|
if (parent instanceof PdfDict) currentDict = parent;
|
|
34211
34274
|
else break;
|
|
34212
34275
|
} else break;
|
|
@@ -34216,13 +34279,13 @@ var PDFPage = class PDFPage {
|
|
|
34216
34279
|
/**
|
|
34217
34280
|
* Create a font resolver function for text extraction.
|
|
34218
34281
|
*/
|
|
34219
|
-
|
|
34220
|
-
const resourcesDict =
|
|
34282
|
+
createFontResolver() {
|
|
34283
|
+
const resourcesDict = this.resolveInheritedResources();
|
|
34221
34284
|
if (!resourcesDict) return () => null;
|
|
34222
34285
|
let fontDict = null;
|
|
34223
34286
|
const fontEntry = resourcesDict.get("Font");
|
|
34224
34287
|
if (fontEntry instanceof PdfRef && this.ctx) {
|
|
34225
|
-
const resolved =
|
|
34288
|
+
const resolved = this.ctx.resolve(fontEntry);
|
|
34226
34289
|
if (resolved instanceof PdfDict) fontDict = resolved;
|
|
34227
34290
|
} else if (fontEntry instanceof PdfDict) fontDict = fontEntry;
|
|
34228
34291
|
if (!fontDict) return () => null;
|
|
@@ -34231,7 +34294,7 @@ var PDFPage = class PDFPage {
|
|
|
34231
34294
|
const name = nameObj.value;
|
|
34232
34295
|
let fontDictEntry = null;
|
|
34233
34296
|
if (fontEntry$1 instanceof PdfRef && this.ctx) {
|
|
34234
|
-
const resolved =
|
|
34297
|
+
const resolved = this.ctx.resolve(fontEntry$1);
|
|
34235
34298
|
if (resolved instanceof PdfDict) fontDictEntry = resolved;
|
|
34236
34299
|
} else if (fontEntry$1 instanceof PdfDict) fontDictEntry = fontEntry$1;
|
|
34237
34300
|
if (!fontDictEntry) continue;
|
|
@@ -34240,36 +34303,36 @@ var PDFPage = class PDFPage {
|
|
|
34240
34303
|
if (toUnicodeEntry && this.ctx) {
|
|
34241
34304
|
let toUnicodeStream = null;
|
|
34242
34305
|
if (toUnicodeEntry instanceof PdfRef) {
|
|
34243
|
-
const resolved =
|
|
34306
|
+
const resolved = this.ctx.resolve(toUnicodeEntry);
|
|
34244
34307
|
if (resolved instanceof PdfStream) toUnicodeStream = resolved;
|
|
34245
34308
|
} else if (toUnicodeEntry instanceof PdfStream) toUnicodeStream = toUnicodeEntry;
|
|
34246
34309
|
if (toUnicodeStream) try {
|
|
34247
|
-
toUnicodeMap = parseToUnicode(
|
|
34310
|
+
toUnicodeMap = parseToUnicode(toUnicodeStream.getDecodedData());
|
|
34248
34311
|
} catch {}
|
|
34249
34312
|
}
|
|
34250
34313
|
const resolvedRefs = /* @__PURE__ */ new Map();
|
|
34251
34314
|
const decodedStreams = /* @__PURE__ */ new Map();
|
|
34252
|
-
const preResolveValue =
|
|
34315
|
+
const preResolveValue = (value) => {
|
|
34253
34316
|
if (!this.ctx) return;
|
|
34254
34317
|
if (value instanceof PdfRef) {
|
|
34255
34318
|
const key$1 = `${value.objectNumber} ${value.generation} R`;
|
|
34256
34319
|
if (resolvedRefs.has(key$1)) return;
|
|
34257
|
-
const resolved =
|
|
34320
|
+
const resolved = this.ctx.resolve(value);
|
|
34258
34321
|
if (resolved instanceof PdfDict || resolved instanceof PdfArray || resolved instanceof PdfStream) {
|
|
34259
34322
|
resolvedRefs.set(key$1, resolved);
|
|
34260
34323
|
if (resolved instanceof PdfStream) try {
|
|
34261
|
-
const decoded =
|
|
34324
|
+
const decoded = resolved.getDecodedData();
|
|
34262
34325
|
decodedStreams.set(key$1, decoded);
|
|
34263
34326
|
} catch {}
|
|
34264
|
-
|
|
34327
|
+
preResolveValue(resolved);
|
|
34265
34328
|
}
|
|
34266
|
-
} else if (value instanceof PdfDict) for (const [, v] of value)
|
|
34267
|
-
else if (value instanceof PdfArray) for (let i = 0; i < value.length; i++)
|
|
34329
|
+
} else if (value instanceof PdfDict) for (const [, v] of value) preResolveValue(v);
|
|
34330
|
+
else if (value instanceof PdfArray) for (let i = 0; i < value.length; i++) preResolveValue(value.at(i));
|
|
34268
34331
|
};
|
|
34269
|
-
|
|
34270
|
-
|
|
34271
|
-
|
|
34272
|
-
|
|
34332
|
+
preResolveValue(fontDictEntry.get("DescendantFonts"));
|
|
34333
|
+
preResolveValue(fontDictEntry.get("FontDescriptor"));
|
|
34334
|
+
preResolveValue(fontDictEntry.get("Encoding"));
|
|
34335
|
+
preResolveValue(fontDictEntry.get("Widths"));
|
|
34273
34336
|
const pdfFont = parseFont(fontDictEntry, {
|
|
34274
34337
|
resolveRef: (ref) => {
|
|
34275
34338
|
if (ref instanceof PdfRef && this.ctx) {
|
|
@@ -34340,17 +34403,16 @@ var PDFPageTree = class PDFPageTree {
|
|
|
34340
34403
|
}
|
|
34341
34404
|
/**
|
|
34342
34405
|
* Load and build the page tree by walking from the root.
|
|
34343
|
-
* This is the only async operation.
|
|
34344
34406
|
*/
|
|
34345
|
-
static
|
|
34407
|
+
static load(pagesRef, getObject) {
|
|
34346
34408
|
const pages = [];
|
|
34347
34409
|
const visited = /* @__PURE__ */ new Set();
|
|
34348
34410
|
const loadedPages = /* @__PURE__ */ new Map();
|
|
34349
|
-
const walk =
|
|
34411
|
+
const walk = (ref) => {
|
|
34350
34412
|
const key$1 = `${ref.objectNumber} ${ref.generation}`;
|
|
34351
34413
|
if (visited.has(key$1)) return;
|
|
34352
34414
|
visited.add(key$1);
|
|
34353
|
-
const node =
|
|
34415
|
+
const node = getObject(ref);
|
|
34354
34416
|
if (!(node instanceof PdfDict)) return;
|
|
34355
34417
|
const type = node.getName("Type")?.value;
|
|
34356
34418
|
if (type === "Page") {
|
|
@@ -34360,12 +34422,12 @@ var PDFPageTree = class PDFPageTree {
|
|
|
34360
34422
|
const kids = node.getArray("Kids");
|
|
34361
34423
|
if (kids) for (let i = 0; i < kids.length; i++) {
|
|
34362
34424
|
const kid = kids.at(i);
|
|
34363
|
-
if (kid instanceof PdfRef)
|
|
34425
|
+
if (kid instanceof PdfRef) walk(kid);
|
|
34364
34426
|
}
|
|
34365
34427
|
}
|
|
34366
34428
|
};
|
|
34367
|
-
|
|
34368
|
-
const root =
|
|
34429
|
+
walk(pagesRef);
|
|
34430
|
+
const root = getObject(pagesRef);
|
|
34369
34431
|
if (!(root instanceof PdfDict)) throw new Error("Root Pages object is not a dictionary");
|
|
34370
34432
|
const getPageDict = (ref) => {
|
|
34371
34433
|
const key$1 = `${ref.objectNumber} ${ref.generation}`;
|
|
@@ -34976,7 +35038,7 @@ async function computeSha1Hex(data) {
|
|
|
34976
35038
|
* ```typescript
|
|
34977
35039
|
* const dssBuilder = await DSSBuilder.fromCatalog(catalog, registry);
|
|
34978
35040
|
* await dssBuilder.addLtvData(ltvData);
|
|
34979
|
-
* const dssRef =
|
|
35041
|
+
* const dssRef = dssBuilder.build();
|
|
34980
35042
|
* catalog.set("DSS", dssRef);
|
|
34981
35043
|
* ```
|
|
34982
35044
|
*/
|
|
@@ -35018,7 +35080,7 @@ var DSSBuilder = class DSSBuilder {
|
|
|
35018
35080
|
let dss;
|
|
35019
35081
|
if (dssVal instanceof PdfDict) dss = dssVal;
|
|
35020
35082
|
else if (dssVal instanceof PdfRef) {
|
|
35021
|
-
const resolved =
|
|
35083
|
+
const resolved = registry.resolve(dssVal);
|
|
35022
35084
|
if (!(resolved instanceof PdfDict)) return builder;
|
|
35023
35085
|
dss = resolved;
|
|
35024
35086
|
} else return builder;
|
|
@@ -35030,7 +35092,7 @@ var DSSBuilder = class DSSBuilder {
|
|
|
35030
35092
|
let vri;
|
|
35031
35093
|
if (vriVal instanceof PdfDict) vri = vriVal;
|
|
35032
35094
|
else if (vriVal instanceof PdfRef) {
|
|
35033
|
-
const resolved =
|
|
35095
|
+
const resolved = registry.resolve(vriVal);
|
|
35034
35096
|
if (!(resolved instanceof PdfDict)) return builder;
|
|
35035
35097
|
vri = resolved;
|
|
35036
35098
|
} else return builder;
|
|
@@ -35040,7 +35102,7 @@ var DSSBuilder = class DSSBuilder {
|
|
|
35040
35102
|
let entry;
|
|
35041
35103
|
if (entryVal instanceof PdfDict) entry = entryVal;
|
|
35042
35104
|
else if (entryVal instanceof PdfRef) {
|
|
35043
|
-
const resolved =
|
|
35105
|
+
const resolved = registry.resolve(entryVal);
|
|
35044
35106
|
if (!(resolved instanceof PdfDict)) continue;
|
|
35045
35107
|
entry = resolved;
|
|
35046
35108
|
} else continue;
|
|
@@ -35106,12 +35168,12 @@ var DSSBuilder = class DSSBuilder {
|
|
|
35106
35168
|
*
|
|
35107
35169
|
* Merges with any existing data loaded via fromCatalog().
|
|
35108
35170
|
*/
|
|
35109
|
-
|
|
35171
|
+
build() {
|
|
35110
35172
|
const dss = new PdfDict();
|
|
35111
35173
|
dss.set("Type", PdfName.of("DSS"));
|
|
35112
|
-
const certRefs =
|
|
35113
|
-
const ocspRefs =
|
|
35114
|
-
const crlRefs =
|
|
35174
|
+
const certRefs = this.buildStreamRefs(this.certMap, this.existingCertRefs);
|
|
35175
|
+
const ocspRefs = this.buildStreamRefs(this.ocspMap, this.existingOcspRefs);
|
|
35176
|
+
const crlRefs = this.buildStreamRefs(this.crlMap, this.existingCrlRefs);
|
|
35115
35177
|
if (certRefs.length > 0) dss.set("Certs", new PdfArray(certRefs));
|
|
35116
35178
|
if (ocspRefs.length > 0) dss.set("OCSPs", new PdfArray(ocspRefs));
|
|
35117
35179
|
if (crlRefs.length > 0) dss.set("CRLs", new PdfArray(crlRefs));
|
|
@@ -35139,13 +35201,13 @@ var DSSBuilder = class DSSBuilder {
|
|
|
35139
35201
|
let arrayVal = dss.get(key$1);
|
|
35140
35202
|
if (!arrayVal) return;
|
|
35141
35203
|
let array;
|
|
35142
|
-
if (arrayVal instanceof PdfRef) arrayVal =
|
|
35204
|
+
if (arrayVal instanceof PdfRef) arrayVal = this.registry.resolve(arrayVal) ?? void 0;
|
|
35143
35205
|
if (arrayVal instanceof PdfArray) array = arrayVal;
|
|
35144
35206
|
if (!array) return;
|
|
35145
35207
|
for (const item of array) if (item instanceof PdfRef) {
|
|
35146
|
-
const stream =
|
|
35208
|
+
const stream = this.registry.resolve(item);
|
|
35147
35209
|
if (stream instanceof PdfStream) {
|
|
35148
|
-
const data =
|
|
35210
|
+
const data = stream.getDecodedData();
|
|
35149
35211
|
const hash = await computeSha1Hex(data);
|
|
35150
35212
|
dataMap.set(hash, {
|
|
35151
35213
|
data,
|
|
@@ -35162,13 +35224,13 @@ var DSSBuilder = class DSSBuilder {
|
|
|
35162
35224
|
const hashes = [];
|
|
35163
35225
|
let arrayVal = entry.get(key$1);
|
|
35164
35226
|
if (!arrayVal) return hashes;
|
|
35165
|
-
if (arrayVal instanceof PdfRef) arrayVal =
|
|
35227
|
+
if (arrayVal instanceof PdfRef) arrayVal = this.registry.resolve(arrayVal) ?? void 0;
|
|
35166
35228
|
const array = arrayVal instanceof PdfArray ? arrayVal : null;
|
|
35167
35229
|
if (!array) return hashes;
|
|
35168
35230
|
for (const item of array) if (item instanceof PdfRef) {
|
|
35169
|
-
const stream =
|
|
35231
|
+
const stream = this.registry.resolve(item);
|
|
35170
35232
|
if (stream instanceof PdfStream) {
|
|
35171
|
-
const data =
|
|
35233
|
+
const data = stream.getDecodedData();
|
|
35172
35234
|
const hash = await computeSha1Hex(data);
|
|
35173
35235
|
hashes.push(hash);
|
|
35174
35236
|
if (!dataMap.has(hash)) dataMap.set(hash, {
|
|
@@ -35182,7 +35244,7 @@ var DSSBuilder = class DSSBuilder {
|
|
|
35182
35244
|
/**
|
|
35183
35245
|
* Build stream refs, reusing existing refs where possible.
|
|
35184
35246
|
*/
|
|
35185
|
-
|
|
35247
|
+
buildStreamRefs(dataMap, existingRefs) {
|
|
35186
35248
|
const refs = [];
|
|
35187
35249
|
for (const [hash, entry] of dataMap) {
|
|
35188
35250
|
let ref = entry.ref ?? existingRefs.get(hash);
|
|
@@ -36258,7 +36320,7 @@ var PDFSignature = class {
|
|
|
36258
36320
|
async sign(options) {
|
|
36259
36321
|
const warnings = [];
|
|
36260
36322
|
const resolved = this.resolveOptions(options);
|
|
36261
|
-
const mdpWarning =
|
|
36323
|
+
const mdpWarning = this.checkMdpViolation();
|
|
36262
36324
|
if (mdpWarning) warnings.push(mdpWarning);
|
|
36263
36325
|
const firstPageRef = this.pdf.context.pages.getPage(0);
|
|
36264
36326
|
if (!firstPageRef) throw new Error("Document has no pages - cannot create signature field");
|
|
@@ -36274,7 +36336,7 @@ var PDFSignature = class {
|
|
|
36274
36336
|
if (resolved.location) signatureDict.set("Location", PdfString.fromString(escapePdfString(resolved.location)));
|
|
36275
36337
|
if (resolved.contactInfo) signatureDict.set("ContactInfo", PdfString.fromString(escapePdfString(resolved.contactInfo)));
|
|
36276
36338
|
const signatureRef = this.pdf.context.registry.register(signatureDict);
|
|
36277
|
-
|
|
36339
|
+
this.findOrCreateSignatureField({
|
|
36278
36340
|
fieldName: resolved.fieldName,
|
|
36279
36341
|
pageRef: firstPageRef,
|
|
36280
36342
|
signatureRef
|
|
@@ -36323,9 +36385,9 @@ var PDFSignature = class {
|
|
|
36323
36385
|
/**
|
|
36324
36386
|
* Find or create a signature field.
|
|
36325
36387
|
*/
|
|
36326
|
-
|
|
36388
|
+
findOrCreateSignatureField(options) {
|
|
36327
36389
|
const { fieldName, pageRef, signatureRef } = options;
|
|
36328
|
-
const form =
|
|
36390
|
+
const form = this.pdf.getOrCreateForm();
|
|
36329
36391
|
const existingNames = /* @__PURE__ */ new Set();
|
|
36330
36392
|
let fieldDict;
|
|
36331
36393
|
const fields = form.getFields();
|
|
@@ -36361,8 +36423,8 @@ var PDFSignature = class {
|
|
|
36361
36423
|
/**
|
|
36362
36424
|
* Check for MDP (certification signature) violations.
|
|
36363
36425
|
*/
|
|
36364
|
-
|
|
36365
|
-
const form =
|
|
36426
|
+
checkMdpViolation() {
|
|
36427
|
+
const form = this.pdf.getForm();
|
|
36366
36428
|
if (!form) return null;
|
|
36367
36429
|
const fields = form.getFields();
|
|
36368
36430
|
for (const field of fields) if (field instanceof SignatureField && field.isSigned()) {
|
|
@@ -36388,11 +36450,11 @@ var PDFSignature = class {
|
|
|
36388
36450
|
*/
|
|
36389
36451
|
async addDss(ltvData) {
|
|
36390
36452
|
const registry = this.pdf.context.registry;
|
|
36391
|
-
const catalogDict =
|
|
36453
|
+
const catalogDict = this.pdf.getCatalog();
|
|
36392
36454
|
if (!catalogDict) throw new Error("Document has no catalog");
|
|
36393
36455
|
const dssBuilder = await DSSBuilder.fromCatalog(catalogDict, registry);
|
|
36394
36456
|
await dssBuilder.addLtvData(ltvData);
|
|
36395
|
-
const dssRef =
|
|
36457
|
+
const dssRef = dssBuilder.build();
|
|
36396
36458
|
catalogDict.set("DSS", dssRef);
|
|
36397
36459
|
const savedBytes = await this.pdf.save({ incremental: true });
|
|
36398
36460
|
await this.pdf.reload(savedBytes);
|
|
@@ -36619,13 +36681,13 @@ var PDF = class PDF {
|
|
|
36619
36681
|
*/
|
|
36620
36682
|
static async load(bytes, options) {
|
|
36621
36683
|
const scanner = new Scanner(bytes);
|
|
36622
|
-
const parsed =
|
|
36684
|
+
const parsed = new DocumentParser(scanner, options).parse();
|
|
36623
36685
|
const registry = new ObjectRegistry(parsed.xref);
|
|
36624
36686
|
let isLinearized = false;
|
|
36625
36687
|
try {
|
|
36626
36688
|
const firstObjNum = Math.min(...parsed.xref.keys());
|
|
36627
36689
|
if (firstObjNum > 0) {
|
|
36628
|
-
const firstObj =
|
|
36690
|
+
const firstObj = parsed.getObject(PdfRef.of(firstObjNum, 0));
|
|
36629
36691
|
if (firstObj instanceof PdfDict && isLinearizationDict(firstObj)) isLinearized = true;
|
|
36630
36692
|
}
|
|
36631
36693
|
} catch {}
|
|
@@ -36641,13 +36703,13 @@ var PDF = class PDF {
|
|
|
36641
36703
|
registry.setResolver((ref) => parsed.getObject(ref));
|
|
36642
36704
|
const rootRef = parsed.trailer.getRef("Root");
|
|
36643
36705
|
if (!rootRef) throw new Error("Document has no catalog (missing /Root in trailer)");
|
|
36644
|
-
const catalogDict =
|
|
36706
|
+
const catalogDict = registry.resolve(rootRef);
|
|
36645
36707
|
if (!catalogDict || !(catalogDict instanceof PdfDict)) throw new Error("Document has no catalog");
|
|
36646
36708
|
const pdfCatalog = new PDFCatalog(catalogDict, registry);
|
|
36647
36709
|
const pagesRef = catalogDict.getRef("Pages");
|
|
36648
|
-
const pages = pagesRef ?
|
|
36710
|
+
const pages = pagesRef ? PDFPageTree.load(pagesRef, parsed.getObject.bind(parsed)) : PDFPageTree.empty();
|
|
36649
36711
|
const infoRef = parsed.trailer.getRef("Info");
|
|
36650
|
-
if (infoRef)
|
|
36712
|
+
if (infoRef) registry.resolve(infoRef);
|
|
36651
36713
|
return new PDF(new PDFContext(registry, pdfCatalog, pages, {
|
|
36652
36714
|
version: parsed.version,
|
|
36653
36715
|
securityHandler: parsed.securityHandler,
|
|
@@ -36672,7 +36734,7 @@ var PDF = class PDF {
|
|
|
36672
36734
|
*/
|
|
36673
36735
|
async reload(bytes) {
|
|
36674
36736
|
const scanner = new Scanner(bytes);
|
|
36675
|
-
const parsed =
|
|
36737
|
+
const parsed = new DocumentParser(scanner).parse();
|
|
36676
36738
|
const registry = new ObjectRegistry(parsed.xref);
|
|
36677
36739
|
registry.setResolver((ref) => parsed.getObject(ref));
|
|
36678
36740
|
const xrefParser = new XRefParser(scanner);
|
|
@@ -36684,11 +36746,11 @@ var PDF = class PDF {
|
|
|
36684
36746
|
}
|
|
36685
36747
|
const rootRef = parsed.trailer.getRef("Root");
|
|
36686
36748
|
if (!rootRef) throw new Error("Document has no catalog");
|
|
36687
|
-
const catalogDict =
|
|
36749
|
+
const catalogDict = registry.resolve(rootRef);
|
|
36688
36750
|
if (!(catalogDict instanceof PdfDict)) throw new Error("Document has no catalog");
|
|
36689
36751
|
const pdfCatalog = new PDFCatalog(catalogDict, registry);
|
|
36690
36752
|
const pagesRef = catalogDict.getRef("Pages");
|
|
36691
|
-
this.ctx = new PDFContext(registry, pdfCatalog, pagesRef ?
|
|
36753
|
+
this.ctx = new PDFContext(registry, pdfCatalog, pagesRef ? PDFPageTree.load(pagesRef, parsed.getObject.bind(parsed)) : PDFPageTree.empty(), {
|
|
36692
36754
|
version: parsed.version,
|
|
36693
36755
|
securityHandler: parsed.securityHandler,
|
|
36694
36756
|
isEncrypted: parsed.isEncrypted,
|
|
@@ -36727,8 +36789,12 @@ var PDF = class PDF {
|
|
|
36727
36789
|
});
|
|
36728
36790
|
const catalogRef = registry.register(catalogDict);
|
|
36729
36791
|
const trailer = PdfDict.of({ Root: catalogRef });
|
|
36730
|
-
registry.setResolver(
|
|
36731
|
-
const pdf = new PDF(new PDFContext(registry, new PDFCatalog(catalogDict, registry), PDFPageTree.fromRoot(pagesRef, pagesDict, (ref) =>
|
|
36792
|
+
registry.setResolver((ref) => registry.getObject(ref));
|
|
36793
|
+
const pdf = new PDF(new PDFContext(registry, new PDFCatalog(catalogDict, registry), PDFPageTree.fromRoot(pagesRef, pagesDict, (ref) => {
|
|
36794
|
+
const obj = registry.getObject(ref);
|
|
36795
|
+
if (obj instanceof PdfDict) return obj;
|
|
36796
|
+
return null;
|
|
36797
|
+
}), {
|
|
36732
36798
|
version: "1.7",
|
|
36733
36799
|
securityHandler: null,
|
|
36734
36800
|
isEncrypted: false,
|
|
@@ -37336,7 +37402,7 @@ var PDF = class PDF {
|
|
|
37336
37402
|
*
|
|
37337
37403
|
* Objects are cached and tracked for modifications.
|
|
37338
37404
|
*/
|
|
37339
|
-
|
|
37405
|
+
getObject(ref) {
|
|
37340
37406
|
return this.ctx.resolve(ref);
|
|
37341
37407
|
}
|
|
37342
37408
|
/**
|
|
@@ -37345,18 +37411,18 @@ var PDF = class PDF {
|
|
|
37345
37411
|
* Note: For internal use, prefer accessing the catalog via context which
|
|
37346
37412
|
* provides higher-level methods for working with catalog structures.
|
|
37347
37413
|
*/
|
|
37348
|
-
|
|
37414
|
+
getCatalog() {
|
|
37349
37415
|
return this.ctx.catalog.getDict();
|
|
37350
37416
|
}
|
|
37351
37417
|
/**
|
|
37352
37418
|
* Get all pages in document order.
|
|
37353
37419
|
*/
|
|
37354
|
-
|
|
37420
|
+
getPages() {
|
|
37355
37421
|
const refs = this.ctx.pages.getPages();
|
|
37356
37422
|
const pages = [];
|
|
37357
37423
|
for (let i = 0; i < refs.length; i++) {
|
|
37358
37424
|
const ref = refs[i];
|
|
37359
|
-
const dict =
|
|
37425
|
+
const dict = this.ctx.resolve(ref);
|
|
37360
37426
|
if (!(dict instanceof PdfDict)) throw new Error(`Page ${i} is not a dictionary`);
|
|
37361
37427
|
pages.push(new PDFPage(ref, dict, i, this.ctx));
|
|
37362
37428
|
}
|
|
@@ -37372,14 +37438,29 @@ var PDF = class PDF {
|
|
|
37372
37438
|
* Get a single page by index (0-based).
|
|
37373
37439
|
* Returns null if index out of bounds.
|
|
37374
37440
|
*/
|
|
37375
|
-
|
|
37441
|
+
getPage(index) {
|
|
37376
37442
|
const ref = this.ctx.pages.getPage(index);
|
|
37377
37443
|
if (!ref) return null;
|
|
37378
|
-
const dict =
|
|
37444
|
+
const dict = this.ctx.resolve(ref);
|
|
37379
37445
|
if (!(dict instanceof PdfDict)) return null;
|
|
37446
|
+
this.ensurePageResourcesResolved(dict);
|
|
37380
37447
|
return new PDFPage(ref, dict, index, this.ctx);
|
|
37381
37448
|
}
|
|
37382
37449
|
/**
|
|
37450
|
+
* Ensure page resources are resolved (not a reference).
|
|
37451
|
+
*
|
|
37452
|
+
* Pages may have Resources as a PdfRef pointing to a shared resources dict.
|
|
37453
|
+
* The sync getResources() method on PDFPage needs the actual dict, not a ref.
|
|
37454
|
+
* This resolves the reference and replaces it in the page dict.
|
|
37455
|
+
*/
|
|
37456
|
+
ensurePageResourcesResolved(pageDict) {
|
|
37457
|
+
const resources = pageDict.get("Resources");
|
|
37458
|
+
if (resources instanceof PdfRef) {
|
|
37459
|
+
const resolved = this.ctx.resolve(resources);
|
|
37460
|
+
if (resolved instanceof PdfDict) pageDict.set("Resources", resolved.clone());
|
|
37461
|
+
}
|
|
37462
|
+
}
|
|
37463
|
+
/**
|
|
37383
37464
|
* Add a new blank page.
|
|
37384
37465
|
*
|
|
37385
37466
|
* @param options - Page size, rotation, and insertion position
|
|
@@ -37489,14 +37570,14 @@ var PDF = class PDF {
|
|
|
37489
37570
|
for (const index of indices) if (index < 0 || index >= source.getPageCount()) throw new RangeError(`Page index ${index} out of bounds (0-${source.getPageCount() - 1})`);
|
|
37490
37571
|
const copiedRefs = [];
|
|
37491
37572
|
for (const index of indices) {
|
|
37492
|
-
const srcPage =
|
|
37573
|
+
const srcPage = source.getPage(index);
|
|
37493
37574
|
if (!srcPage) throw new Error(`Source page ${index} not found`);
|
|
37494
37575
|
const copiedPageRef = await copier.copyPage(srcPage.ref);
|
|
37495
37576
|
copiedRefs.push(copiedPageRef);
|
|
37496
37577
|
}
|
|
37497
37578
|
let insertIndex = options.insertAt ?? this.getPageCount();
|
|
37498
37579
|
for (const copiedRef of copiedRefs) {
|
|
37499
|
-
const copiedDict =
|
|
37580
|
+
const copiedDict = this.getObject(copiedRef);
|
|
37500
37581
|
if (!(copiedDict instanceof PdfDict)) throw new Error("Copied page is not a dictionary");
|
|
37501
37582
|
this.ctx.pages.insertPage(insertIndex, copiedRef, copiedDict);
|
|
37502
37583
|
const page = new PDFPage(copiedRef, copiedDict, insertIndex, this.ctx);
|
|
@@ -37560,18 +37641,18 @@ var PDF = class PDF {
|
|
|
37560
37641
|
* ```
|
|
37561
37642
|
*/
|
|
37562
37643
|
async embedPage(source, pageIndex) {
|
|
37563
|
-
const srcPage =
|
|
37644
|
+
const srcPage = source.getPage(pageIndex);
|
|
37564
37645
|
if (!srcPage) throw new RangeError(`Page index ${pageIndex} out of bounds`);
|
|
37565
|
-
const contentData =
|
|
37646
|
+
const contentData = this.getPageContentData(source, srcPage);
|
|
37566
37647
|
const copier = new ObjectCopier(source, this, { includeAnnotations: false });
|
|
37567
|
-
|
|
37568
|
-
let resources;
|
|
37569
|
-
if (srcResources instanceof
|
|
37570
|
-
|
|
37571
|
-
const
|
|
37572
|
-
if (
|
|
37573
|
-
|
|
37574
|
-
|
|
37648
|
+
let srcResources = srcPage.dict.get("Resources");
|
|
37649
|
+
let resources = void 0;
|
|
37650
|
+
if (srcResources instanceof PdfRef) srcResources = source.getObject(srcResources) ?? void 0;
|
|
37651
|
+
if (srcResources instanceof PdfDict) {
|
|
37652
|
+
const copied = await copier.copyObject(srcResources);
|
|
37653
|
+
if (copied instanceof PdfDict) resources = copied;
|
|
37654
|
+
}
|
|
37655
|
+
if (!resources) resources = new PdfDict();
|
|
37575
37656
|
const mediaBox = srcPage.getMediaBox();
|
|
37576
37657
|
const formXObject = PdfStream.fromDict({
|
|
37577
37658
|
Type: PdfName.of("XObject"),
|
|
@@ -37590,12 +37671,12 @@ var PDF = class PDF {
|
|
|
37590
37671
|
/**
|
|
37591
37672
|
* Get the concatenated content stream data from a page.
|
|
37592
37673
|
*/
|
|
37593
|
-
|
|
37674
|
+
getPageContentData(source, page) {
|
|
37594
37675
|
const contents = page.dict.get("Contents");
|
|
37595
37676
|
if (!contents) return new Uint8Array(0);
|
|
37596
37677
|
if (contents instanceof PdfRef) {
|
|
37597
|
-
const stream =
|
|
37598
|
-
if (stream instanceof PdfStream) return
|
|
37678
|
+
const stream = source.getObject(contents);
|
|
37679
|
+
if (stream instanceof PdfStream) return stream.getDecodedData();
|
|
37599
37680
|
return new Uint8Array(0);
|
|
37600
37681
|
}
|
|
37601
37682
|
if (contents instanceof PdfArray) {
|
|
@@ -37603,10 +37684,10 @@ var PDF = class PDF {
|
|
|
37603
37684
|
for (let i = 0; i < contents.length; i++) {
|
|
37604
37685
|
const ref = contents.at(i);
|
|
37605
37686
|
if (ref instanceof PdfRef) {
|
|
37606
|
-
const stream =
|
|
37687
|
+
const stream = source.getObject(ref);
|
|
37607
37688
|
if (stream instanceof PdfStream) {
|
|
37608
37689
|
if (chunks.length > 0) chunks.push(new Uint8Array([10]));
|
|
37609
|
-
chunks.push(
|
|
37690
|
+
chunks.push(stream.getDecodedData());
|
|
37610
37691
|
}
|
|
37611
37692
|
}
|
|
37612
37693
|
}
|
|
@@ -37619,7 +37700,7 @@ var PDF = class PDF {
|
|
|
37619
37700
|
}
|
|
37620
37701
|
return result;
|
|
37621
37702
|
}
|
|
37622
|
-
if (contents instanceof PdfStream) return
|
|
37703
|
+
if (contents instanceof PdfStream) return contents.getDecodedData();
|
|
37623
37704
|
return new Uint8Array(0);
|
|
37624
37705
|
}
|
|
37625
37706
|
/**
|
|
@@ -37719,7 +37800,7 @@ var PDF = class PDF {
|
|
|
37719
37800
|
* page.drawImage(image, { x: 50, y: 500 });
|
|
37720
37801
|
* ```
|
|
37721
37802
|
*/
|
|
37722
|
-
|
|
37803
|
+
embedImage(bytes) {
|
|
37723
37804
|
if (isJpeg(bytes)) return this.embedJpeg(bytes);
|
|
37724
37805
|
if (isPng(bytes)) return this.embedPng(bytes);
|
|
37725
37806
|
throw new Error("Unsupported image format. Only JPEG and PNG are supported.");
|
|
@@ -37744,7 +37825,7 @@ var PDF = class PDF {
|
|
|
37744
37825
|
* });
|
|
37745
37826
|
* ```
|
|
37746
37827
|
*/
|
|
37747
|
-
|
|
37828
|
+
embedJpeg(bytes) {
|
|
37748
37829
|
const info = parseJpegHeader(bytes);
|
|
37749
37830
|
const stream = PdfStream.fromDict({
|
|
37750
37831
|
Type: PdfName.of("XObject"),
|
|
@@ -37775,7 +37856,7 @@ var PDF = class PDF {
|
|
|
37775
37856
|
* page.drawImage(logo, { x: 100, y: 700, width: 150 });
|
|
37776
37857
|
* ```
|
|
37777
37858
|
*/
|
|
37778
|
-
|
|
37859
|
+
embedPng(bytes) {
|
|
37779
37860
|
const { info, pixels, alpha } = parsePng(bytes);
|
|
37780
37861
|
const compressedPixels = deflate(pixels);
|
|
37781
37862
|
const dictEntries = {
|
|
@@ -37834,7 +37915,7 @@ var PDF = class PDF {
|
|
|
37834
37915
|
*
|
|
37835
37916
|
* @returns Map of attachment name to attachment info
|
|
37836
37917
|
*/
|
|
37837
|
-
|
|
37918
|
+
getAttachments() {
|
|
37838
37919
|
return this.attachments.list();
|
|
37839
37920
|
}
|
|
37840
37921
|
/**
|
|
@@ -37845,7 +37926,7 @@ var PDF = class PDF {
|
|
|
37845
37926
|
* @param name The attachment name (key in the EmbeddedFiles tree)
|
|
37846
37927
|
* @returns The attachment bytes, or null if not found
|
|
37847
37928
|
*/
|
|
37848
|
-
|
|
37929
|
+
getAttachment(name) {
|
|
37849
37930
|
return this.attachments.get(name);
|
|
37850
37931
|
}
|
|
37851
37932
|
/**
|
|
@@ -37856,7 +37937,7 @@ var PDF = class PDF {
|
|
|
37856
37937
|
* @param name The attachment name
|
|
37857
37938
|
* @returns True if the attachment exists
|
|
37858
37939
|
*/
|
|
37859
|
-
|
|
37940
|
+
hasAttachment(name) {
|
|
37860
37941
|
return this.attachments.has(name);
|
|
37861
37942
|
}
|
|
37862
37943
|
/**
|
|
@@ -37869,7 +37950,7 @@ var PDF = class PDF {
|
|
|
37869
37950
|
* @param options - Attachment options (description, MIME type, dates)
|
|
37870
37951
|
* @throws {Error} If name already exists and overwrite !== true
|
|
37871
37952
|
*/
|
|
37872
|
-
|
|
37953
|
+
addAttachment(name, data, options = {}) {
|
|
37873
37954
|
return this.attachments.add(name, data, options);
|
|
37874
37955
|
}
|
|
37875
37956
|
/**
|
|
@@ -37880,7 +37961,7 @@ var PDF = class PDF {
|
|
|
37880
37961
|
* @param name The attachment name
|
|
37881
37962
|
* @returns True if the attachment was removed, false if not found
|
|
37882
37963
|
*/
|
|
37883
|
-
|
|
37964
|
+
removeAttachment(name) {
|
|
37884
37965
|
return this.attachments.remove(name);
|
|
37885
37966
|
}
|
|
37886
37967
|
/**
|
|
@@ -37932,8 +38013,8 @@ var PDF = class PDF {
|
|
|
37932
38013
|
* await pdf.save({ incremental: true });
|
|
37933
38014
|
* ```
|
|
37934
38015
|
*/
|
|
37935
|
-
|
|
37936
|
-
if (this._form === void 0) this._form =
|
|
38016
|
+
getForm() {
|
|
38017
|
+
if (this._form === void 0) this._form = PDFForm.load(this.ctx);
|
|
37937
38018
|
return this._form;
|
|
37938
38019
|
}
|
|
37939
38020
|
/**
|
|
@@ -37951,8 +38032,8 @@ var PDF = class PDF {
|
|
|
37951
38032
|
* const nameField = form.createTextField("name", { fontSize: 12 });
|
|
37952
38033
|
* ```
|
|
37953
38034
|
*/
|
|
37954
|
-
|
|
37955
|
-
const existing =
|
|
38035
|
+
getOrCreateForm() {
|
|
38036
|
+
const existing = this.getForm();
|
|
37956
38037
|
if (existing) return existing;
|
|
37957
38038
|
const helveticaDict = PdfDict.of({
|
|
37958
38039
|
Type: PdfName.of("Font"),
|
|
@@ -37976,9 +38057,8 @@ var PDF = class PDF {
|
|
|
37976
38057
|
NeedAppearances: PdfBool.of(false)
|
|
37977
38058
|
});
|
|
37978
38059
|
const acroFormRef = this.ctx.registry.register(acroFormDict);
|
|
37979
|
-
|
|
37980
|
-
|
|
37981
|
-
this._form = await PDFForm.load(this.ctx);
|
|
38060
|
+
this.getCatalog().set("AcroForm", acroFormRef);
|
|
38061
|
+
this._form = PDFForm.load(this.ctx);
|
|
37982
38062
|
if (!this._form) throw new Error("Failed to create form");
|
|
37983
38063
|
return this._form;
|
|
37984
38064
|
}
|
|
@@ -38033,7 +38113,7 @@ var PDF = class PDF {
|
|
|
38033
38113
|
* }
|
|
38034
38114
|
* ```
|
|
38035
38115
|
*/
|
|
38036
|
-
|
|
38116
|
+
hasLayers() {
|
|
38037
38117
|
return hasLayers(this.ctx);
|
|
38038
38118
|
}
|
|
38039
38119
|
/**
|
|
@@ -38052,7 +38132,7 @@ var PDF = class PDF {
|
|
|
38052
38132
|
* }
|
|
38053
38133
|
* ```
|
|
38054
38134
|
*/
|
|
38055
|
-
|
|
38135
|
+
getLayers() {
|
|
38056
38136
|
return getLayers(this.ctx);
|
|
38057
38137
|
}
|
|
38058
38138
|
/**
|
|
@@ -38084,7 +38164,7 @@ var PDF = class PDF {
|
|
|
38084
38164
|
* await pdf.sign({ signer });
|
|
38085
38165
|
* ```
|
|
38086
38166
|
*/
|
|
38087
|
-
|
|
38167
|
+
flattenLayers() {
|
|
38088
38168
|
return flattenLayers(this.ctx);
|
|
38089
38169
|
}
|
|
38090
38170
|
/**
|
|
@@ -38103,10 +38183,10 @@ var PDF = class PDF {
|
|
|
38103
38183
|
* }
|
|
38104
38184
|
* ```
|
|
38105
38185
|
*/
|
|
38106
|
-
|
|
38107
|
-
const pages =
|
|
38186
|
+
extractText() {
|
|
38187
|
+
const pages = this.getPages();
|
|
38108
38188
|
const results = [];
|
|
38109
|
-
for (const page of pages) results.push(
|
|
38189
|
+
for (const page of pages) results.push(page.extractText());
|
|
38110
38190
|
return results;
|
|
38111
38191
|
}
|
|
38112
38192
|
/**
|
|
@@ -38131,12 +38211,12 @@ var PDF = class PDF {
|
|
|
38131
38211
|
* const placeholders = await pdf.findText(/\{\{\s*\w+\s*\}\}/g);
|
|
38132
38212
|
* ```
|
|
38133
38213
|
*/
|
|
38134
|
-
|
|
38135
|
-
const pages =
|
|
38214
|
+
findText(query, options = {}) {
|
|
38215
|
+
const pages = this.getPages();
|
|
38136
38216
|
const pagesToSearch = options.pages ?? Array.from({ length: pages.length }, (_, i) => i);
|
|
38137
38217
|
const results = [];
|
|
38138
38218
|
for (const pageIndex of pagesToSearch) if (pageIndex >= 0 && pageIndex < pages.length) {
|
|
38139
|
-
const matches =
|
|
38219
|
+
const matches = pages[pageIndex].findText(query, options);
|
|
38140
38220
|
results.push(...matches);
|
|
38141
38221
|
}
|
|
38142
38222
|
return results;
|
|
@@ -38171,14 +38251,14 @@ var PDF = class PDF {
|
|
|
38171
38251
|
* @throws {Error} If document has no catalog (missing /Root in trailer)
|
|
38172
38252
|
*/
|
|
38173
38253
|
async save(options = {}) {
|
|
38174
|
-
return
|
|
38254
|
+
return this.saveInternal(options).bytes;
|
|
38175
38255
|
}
|
|
38176
38256
|
/**
|
|
38177
38257
|
* Internal save that returns full result including xref offset.
|
|
38178
38258
|
* Used by signing to chain incremental updates.
|
|
38179
38259
|
*/
|
|
38180
|
-
|
|
38181
|
-
|
|
38260
|
+
saveInternal(options = {}) {
|
|
38261
|
+
this.fonts.finalize(options.subsetFonts ?? false);
|
|
38182
38262
|
const wantsIncremental = options.incremental ?? false;
|
|
38183
38263
|
const blocker = this.canSaveIncrementally();
|
|
38184
38264
|
if (wantsIncremental && blocker !== null) this.ctx.registry.addWarning(`Incremental save not possible (${blocker}), performing full save`);
|
|
@@ -38215,7 +38295,7 @@ var PDF = class PDF {
|
|
|
38215
38295
|
}
|
|
38216
38296
|
const useXRefStream = options.useXRefStream ?? (useIncremental ? this.usesXRefStreams : false);
|
|
38217
38297
|
if (useIncremental) {
|
|
38218
|
-
const result$1 =
|
|
38298
|
+
const result$1 = writeIncremental(this.ctx.registry, {
|
|
38219
38299
|
originalBytes: this.originalBytes,
|
|
38220
38300
|
originalXRefOffset: this.originalXRefOffset,
|
|
38221
38301
|
root,
|
|
@@ -38228,8 +38308,8 @@ var PDF = class PDF {
|
|
|
38228
38308
|
this._pendingSecurity = { action: "none" };
|
|
38229
38309
|
return result$1;
|
|
38230
38310
|
}
|
|
38231
|
-
|
|
38232
|
-
const result =
|
|
38311
|
+
this.ensureObjectsLoaded();
|
|
38312
|
+
const result = writeComplete(this.ctx.registry, {
|
|
38233
38313
|
version: this.ctx.info.version,
|
|
38234
38314
|
root,
|
|
38235
38315
|
info: infoRef ?? void 0,
|
|
@@ -38246,22 +38326,22 @@ var PDF = class PDF {
|
|
|
38246
38326
|
*
|
|
38247
38327
|
* Walks from the catalog to load all referenced objects.
|
|
38248
38328
|
*/
|
|
38249
|
-
|
|
38329
|
+
ensureObjectsLoaded() {
|
|
38250
38330
|
const visited = /* @__PURE__ */ new Set();
|
|
38251
|
-
const walk =
|
|
38331
|
+
const walk = (obj) => {
|
|
38252
38332
|
if (obj === null) return;
|
|
38253
38333
|
if (obj instanceof PdfRef) {
|
|
38254
38334
|
const key$1 = `${obj.objectNumber} ${obj.generation}`;
|
|
38255
38335
|
if (visited.has(key$1)) return;
|
|
38256
38336
|
visited.add(key$1);
|
|
38257
|
-
|
|
38258
|
-
} else if (obj instanceof PdfDict) for (const [, value] of obj)
|
|
38259
|
-
else if (obj instanceof PdfArray) for (const item of obj)
|
|
38337
|
+
walk(this.getObject(obj));
|
|
38338
|
+
} else if (obj instanceof PdfDict) for (const [, value] of obj) walk(value);
|
|
38339
|
+
else if (obj instanceof PdfArray) for (const item of obj) walk(item);
|
|
38260
38340
|
};
|
|
38261
38341
|
const root = this.ctx.info.trailer.getRef("Root");
|
|
38262
|
-
if (root)
|
|
38342
|
+
if (root) walk(root);
|
|
38263
38343
|
const infoRef = this.ctx.info.trailer.getRef("Info");
|
|
38264
|
-
if (infoRef)
|
|
38344
|
+
if (infoRef) walk(infoRef);
|
|
38265
38345
|
}
|
|
38266
38346
|
};
|
|
38267
38347
|
|
|
@@ -38645,7 +38725,8 @@ const GrpcStatus = {
|
|
|
38645
38725
|
* Type guard for gRPC errors from Google Cloud libraries.
|
|
38646
38726
|
*/
|
|
38647
38727
|
function isGrpcError(error) {
|
|
38648
|
-
|
|
38728
|
+
const grpcError = error;
|
|
38729
|
+
return grpcError instanceof Error && typeof grpcError.code === "number" && grpcError.code >= 0 && grpcError.code <= 16;
|
|
38649
38730
|
}
|
|
38650
38731
|
/**
|
|
38651
38732
|
* Signer that uses Google Cloud KMS for signing operations.
|
|
@@ -38813,6 +38894,7 @@ var GoogleKmsSigner = class GoogleKmsSigner {
|
|
|
38813
38894
|
digest: { [digestKey]: digest }
|
|
38814
38895
|
});
|
|
38815
38896
|
if (!response.signature) throw new KmsSignerError("KMS did not return a signature");
|
|
38897
|
+
if (typeof response.signature === "string") return new TextEncoder().encode(response.signature);
|
|
38816
38898
|
return new Uint8Array(response.signature);
|
|
38817
38899
|
} catch (error) {
|
|
38818
38900
|
if (error instanceof KmsSignerError) throw error;
|