modern-pdf-lib 0.12.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { $ as setFillColor, $t as showTextArray, A as endMarkedContent, At as moveTo, B as saveState, Bt as endText, C as beginArtifact, Ct as ellipsePath, D as beginMarkedContentWithProperties, Dt as fillEvenOdd, E as beginMarkedContentSequence, Et as fillAndStroke, F as radians, Ft as setLineJoin, G as applyFillColor, Gt as setFont, H as setGraphicsState, Ht as moveTextSetLeading, I as radiansToDegrees, It as setLineWidth, J as colorToComponents, Jt as setTextMatrix, K as applyStrokeColor, Kt as setFontSize, L as restoreState, Lt as setMiterLimit, M as concatMatrix, Mt as setDashPattern, N as degrees, Nt as setFlatness, O as createMarkedContentScope, Ot as fillEvenOddAndStroke, P as degreesToRadians, Pt as setLineCap, Q as setColorSpace, Qt as showText, R as rotate, Rt as stroke, S as createAnnotation, St as curveToInitial, T as beginMarkedContent, Tt as fill, U as skew, Ut as nextLine, V as scale, Vt as moveText, W as translate, Wt as setCharacterSpacing, X as grayscale, Xt as setTextRise, Y as componentsToColor, Yt as setTextRenderingMode, Z as rgb, Zt as setWordSpacing, _ as parseSvgTransform, _t as closeFillAndStroke, a as applyRedactions, at as setStrokeColorCmyk, b as annotationFromDict, bt as curveTo, c as PdfLayer, ct as setStrokeColorSpace, d as endLayerContent, dt as drawImageXObject, en as showTextHex, et as setFillColorCmyk, f as drawSvgOnPage, ft as drawXObject, g as parseSvgPath, gt as closeAndStroke, h as parseSvgColor, ht as clipEvenOdd, i as wrapText, it as setStrokeColor, j as wrapInMarkedContent, jt as rectangle, k as endArtifact, kt as lineTo, l as PdfLayerManager, lt as setStrokingColor, m as parseSvg, mt as clip, n as PdfPage, nn as showTextWithSpacing, nt as setFillColorRgb, o as getRedactionMarks, ot as setStrokeColorGray, p as svgToPdfOperators, pt as circlePath, q as cmyk, qt as setLeading, rt as setFillingColor, s as markForRedaction, st as setStrokeColorRgb, t as PageSizes, tn as showTextNextLine, tt as setFillColorGray, u as beginLayerContent, ut as drawImageWithMatrix, v as AnnotationFlags, vt as closeFillEvenOddAndStroke, w as beginArtifactWithType, wt as endPath, x as buildAnnotationDict, xt as curveToFinal, y as PdfAnnotation, yt as closePath, z as rotationMatrix, zt as beginText } from "./pdfPage-JiCJLV3x.mjs";
2
- import { a as formatPdfDate, c as PdfBool, d as PdfNull, f as PdfNumber, g as PdfString, h as PdfStream, i as buildPageTree, l as PdfDict, m as PdfRef, n as buildDocumentStructure, p as PdfObjectRegistry, r as buildInfoDict, s as PdfArray, t as buildCatalog, u as PdfName } from "./pdfCatalog-CTfeeqtF.mjs";
3
- import { n as isAvailable, t as deflateSync$1 } from "./libdeflateWasm-CRFwmrSl.mjs";
1
+ import { $ as colorToComponents, $t as setTextMatrix, A as beginMarkedContent, At as fill, B as radians, Bt as setLineJoin, C as AnnotationFlags, Ct as closeFillEvenOddAndStroke, D as createAnnotation, Dt as curveToInitial, E as buildAnnotationDict, Et as curveToFinal, F as endMarkedContent, Ft as moveTo, G as saveState, Gt as endText, H as restoreState, Ht as setMiterLimit, I as wrapInMarkedContent, It as rectangle, J as skew, Jt as nextLine, K as scale, Kt as moveText, L as concatMatrix, Lt as setDashPattern, M as beginMarkedContentWithProperties, Mt as fillEvenOdd, N as createMarkedContentScope, Nt as fillEvenOddAndStroke, O as beginArtifact, Ot as ellipsePath, P as endArtifact, Pt as lineTo, Q as cmyk, Qt as setLeading, R as degrees, Rt as setFlatness, S as parseSvgTransform, St as closeFillAndStroke, T as annotationFromDict, Tt as curveTo, U as rotate, Ut as stroke, V as radiansToDegrees, Vt as setLineWidth, W as rotationMatrix, Wt as beginText, X as applyFillColor, Xt as setFont, Y as translate, Yt as setCharacterSpacing, Z as applyStrokeColor, Zt as setFontSize, _ as drawSvgOnPage, _t as drawXObject, a as buildGradientObjects, an as showTextHex, at as setFillColorCmyk, b as parseSvgColor, bt as clipEvenOdd, c as radialGradient, ct as setFillingColor, d as getRedactionMarks, dt as setStrokeColorGray, en as setTextRenderingMode, et as componentsToColor, f as markForRedaction, ft as setStrokeColorRgb, g as endLayerContent, gt as drawImageXObject, h as beginLayerContent, ht as drawImageWithMatrix, i as wrapText, in as showTextArray, it as setFillColor, j as beginMarkedContentSequence, jt as fillAndStroke, k as beginArtifactWithType, kt as endPath, l as tilingPattern, lt as setStrokeColor, m as PdfLayerManager, mt as setStrokingColor, n as PdfPage, nn as setWordSpacing, nt as rgb, o as buildPatternObjects, on as showTextNextLine, ot as setFillColorGray, p as PdfLayer, pt as setStrokeColorSpace, q as setGraphicsState, qt as moveTextSetLeading, rn as showText, rt as setColorSpace, s as linearGradient, sn as showTextWithSpacing, st as setFillColorRgb, t as PageSizes, tn as setTextRise, tt as grayscale, u as applyRedactions, ut as setStrokeColorCmyk, v as svgToPdfOperators, vt as circlePath, w as PdfAnnotation, wt as closePath, x as parseSvgPath, xt as closeAndStroke, y as parseSvg, yt as clip, z as degreesToRadians, zt as setLineCap } from "./pdfPage-N1K2U3jI.mjs";
2
+ import { a as formatPdfDate, c as PdfBool, d as PdfNull, f as PdfNumber, g as PdfString, h as PdfStream, i as buildPageTree, l as PdfDict, m as PdfRef, n as buildDocumentStructure, p as PdfObjectRegistry, r as buildInfoDict, s as PdfArray, t as buildCatalog, u as PdfName } from "./pdfCatalog-BB2Wnmud.mjs";
3
+ import { n as isAvailable, t as deflateSync$1 } from "./libdeflateWasm-DlHgU5oy.mjs";
4
4
  import { i as subsetFont, n as computeSubsetTag, t as buildSubsetCmap } from "./fontSubset-ZpLoOZ2e.mjs";
5
- import { t as embedPng } from "./pngEmbed-CHyesD7i.mjs";
5
+ import { t as embedPng } from "./pngEmbed-DTOqgEUC.mjs";
6
6
  import { t as decompressSync } from "./fflateAdapter-DX0VqT5k.mjs";
7
7
  import { deflateSync, inflateSync, unzlibSync } from "fflate";
8
8
 
@@ -199,20 +199,19 @@ var PdfWriter = class {
199
199
  */
200
200
  writeObjectStream(entries, xrefEntries) {
201
201
  const serializedObjects = [];
202
- new StringByteWriter();
203
202
  for (const entry of entries) {
204
203
  const objWriter = new StringByteWriter();
205
204
  entry.object.serialize(objWriter);
206
205
  serializedObjects.push(objWriter.toUint8Array());
207
206
  }
208
- let headerStr = "";
207
+ const headerParts = [];
209
208
  let dataOffset = 0;
210
209
  for (let i = 0; i < entries.length; i++) {
211
- if (i > 0) headerStr += " ";
212
- headerStr += `${entries[i].ref.objectNumber} ${dataOffset}`;
210
+ headerParts.push(`${entries[i].ref.objectNumber} ${dataOffset}`);
213
211
  dataOffset += serializedObjects[i].length;
214
212
  if (i < entries.length - 1) dataOffset += 1;
215
213
  }
214
+ const headerStr = headerParts.join(" ");
216
215
  const headerBytes = encoder$5.encode(headerStr + " ");
217
216
  const firstOffset = headerBytes.length;
218
217
  let totalDataLen = firstOffset;
@@ -3235,7 +3234,7 @@ function extractMetricsWasm(fontData) {
3235
3234
  * Tracks which glyphs have been used so that subsetting can be
3236
3235
  * performed at save time, and provides text measurement methods.
3237
3236
  *
3238
- * Create via {@link embedFont}.
3237
+ * Create via `PdfDocument.embedFont()`.
3239
3238
  */
3240
3239
  var EmbeddedFont = class {
3241
3240
  /** The raw font file bytes. */
@@ -3580,6 +3579,53 @@ function findTable(data, tag) {
3580
3579
  }
3581
3580
  }
3582
3581
 
3582
+ //#endregion
3583
+ //#region src/parser/parseError.ts
3584
+ /**
3585
+ * @module parser/parseError
3586
+ * Structured error class for PDF parsing failures.
3587
+ * @packageDocumentation
3588
+ */
3589
+ var PdfParseError = class extends Error {
3590
+ name = "PdfParseError";
3591
+ offset;
3592
+ expected;
3593
+ actual;
3594
+ hexContext;
3595
+ constructor(options) {
3596
+ const hexCtx = options.data ? formatHexContext(options.data, options.offset) : "";
3597
+ const parts = [options.message];
3598
+ if (options.expected) parts.push(` Expected: ${options.expected}`);
3599
+ if (options.actual) parts.push(` Got: ${options.actual}`);
3600
+ if (hexCtx) parts.push(` Context:\n${hexCtx}`);
3601
+ super(parts.join("\n"), options.cause ? { cause: options.cause } : void 0);
3602
+ this.offset = options.offset;
3603
+ this.expected = options.expected ?? "";
3604
+ this.actual = options.actual ?? "";
3605
+ this.hexContext = hexCtx;
3606
+ }
3607
+ };
3608
+ function formatHexContext(data, offset, windowSize = 16) {
3609
+ const start = Math.max(0, offset - windowSize);
3610
+ const end = Math.min(data.length, offset + windowSize);
3611
+ const slice = data.subarray(start, end);
3612
+ const hexParts = [];
3613
+ const asciiParts = [];
3614
+ for (let i = 0; i < slice.length; i++) {
3615
+ const byte = slice[i];
3616
+ const isErrorByte = start + i === offset;
3617
+ const hex = byte.toString(16).padStart(2, "0");
3618
+ hexParts.push(isErrorByte ? `[${hex}]` : ` ${hex} `);
3619
+ asciiParts.push(byte >= 32 && byte <= 126 ? String.fromCharCode(byte) : ".");
3620
+ }
3621
+ return [
3622
+ ` Offset ${start}:`,
3623
+ ` Hex: ${hexParts.join("")}`,
3624
+ ` ASCII: ${asciiParts.join(" ")}`,
3625
+ ` Error at offset ${offset} (marked with [])`
3626
+ ].join("\n");
3627
+ }
3628
+
3583
3629
  //#endregion
3584
3630
  //#region src/parser/lexer.ts
3585
3631
  /**
@@ -3707,7 +3753,7 @@ const isDelimiter = /* @__PURE__ */ (() => {
3707
3753
  * `hexVal[b]` is the numeric value (0-15) of a hex character, or -1 if
3708
3754
  * the byte is not a valid hex digit.
3709
3755
  */
3710
- const hexVal = /* @__PURE__ */ (() => {
3756
+ const hexVal$1 = /* @__PURE__ */ (() => {
3711
3757
  const t = new Int8Array(256).fill(-1);
3712
3758
  for (let i = 0; i <= 9; i++) t[CH_0 + i] = i;
3713
3759
  for (let i = 0; i < 6; i++) {
@@ -3735,7 +3781,7 @@ const hexVal = /* @__PURE__ */ (() => {
3735
3781
  */
3736
3782
  var PdfLexer = class {
3737
3783
  /** The raw PDF bytes being tokenized. */
3738
- data;
3784
+ _data;
3739
3785
  /** Total length of the input (cached for hot loops). */
3740
3786
  len;
3741
3787
  /** Current read position (byte offset). */
@@ -3758,11 +3804,20 @@ var PdfLexer = class {
3758
3804
  * must not mutate it while the lexer is in use.
3759
3805
  */
3760
3806
  constructor(data) {
3761
- this.data = data;
3807
+ this._data = data;
3762
3808
  this.len = data.length;
3763
3809
  this.position = 0;
3764
3810
  }
3765
3811
  /**
3812
+ * Public accessor for the raw PDF byte buffer.
3813
+ *
3814
+ * This allows other parsers (e.g. object parser, xref parser) to
3815
+ * include hex-context dumps in structured error messages.
3816
+ */
3817
+ get rawData() {
3818
+ return this._data;
3819
+ }
3820
+ /**
3766
3821
  * Consume and return the next token.
3767
3822
  *
3768
3823
  * Returns a token with `type === TokenType.EOF` when the input is
@@ -3798,8 +3853,14 @@ var PdfLexer = class {
3798
3853
  * @throws If there are not enough bytes remaining.
3799
3854
  */
3800
3855
  readStreamData(length) {
3801
- if (this.position + length > this.len) throw new Error(`PdfLexer.readStreamData: requested ${length} bytes at offset ${this.position}, but only ${this.len - this.position} remain`);
3802
- const slice = this.data.subarray(this.position, this.position + length);
3856
+ if (this.position + length > this.len) throw new PdfParseError({
3857
+ message: `PdfLexer.readStreamData: requested ${length} bytes at offset ${this.position}, but only ${this.len - this.position} remain`,
3858
+ offset: this.position,
3859
+ expected: `${length} bytes available`,
3860
+ actual: `${this.len - this.position} bytes remaining`,
3861
+ data: this._data
3862
+ });
3863
+ const slice = this._data.subarray(this.position, this.position + length);
3803
3864
  this.position += length;
3804
3865
  return slice;
3805
3866
  }
@@ -3812,7 +3873,13 @@ var PdfLexer = class {
3812
3873
  * @throws If the offset is out of range.
3813
3874
  */
3814
3875
  seek(offset) {
3815
- if (offset < 0 || offset > this.len) throw new RangeError(`PdfLexer.seek: offset ${offset} is outside [0, ${this.len}]`);
3876
+ if (offset < 0 || offset > this.len) throw new PdfParseError({
3877
+ message: `PdfLexer.seek: offset ${offset} is outside [0, ${this.len}]`,
3878
+ offset,
3879
+ expected: `offset in range [0, ${this.len}]`,
3880
+ actual: `${offset}`,
3881
+ data: this._data
3882
+ });
3816
3883
  this.position = offset;
3817
3884
  this.peeked = null;
3818
3885
  }
@@ -3825,7 +3892,7 @@ var PdfLexer = class {
3825
3892
  */
3826
3893
  byteAt(offset) {
3827
3894
  if (offset < 0 || offset >= this.len) return -1;
3828
- return this.data[offset];
3895
+ return this._data[offset];
3829
3896
  }
3830
3897
  /**
3831
3898
  * Return the total length of the input buffer (in bytes).
@@ -3841,7 +3908,7 @@ var PdfLexer = class {
3841
3908
  * extracting stream data.
3842
3909
  */
3843
3910
  skipWhitespace() {
3844
- const d = this.data;
3911
+ const d = this._data;
3845
3912
  let pos = this.position;
3846
3913
  while (pos < this.len) {
3847
3914
  const b = d[pos];
@@ -3875,7 +3942,7 @@ var PdfLexer = class {
3875
3942
  value: null,
3876
3943
  offset: this.position
3877
3944
  };
3878
- const d = this.data;
3945
+ const d = this._data;
3879
3946
  const startPos = this.position;
3880
3947
  const b = d[startPos];
3881
3948
  if (b === CH_LBRACKET) {
@@ -3915,7 +3982,13 @@ var PdfLexer = class {
3915
3982
  };
3916
3983
  }
3917
3984
  this.position++;
3918
- throw new Error(`PdfLexer: unexpected '>' at offset ${startPos} (expected '>>' for dict end)`);
3985
+ throw new PdfParseError({
3986
+ message: `PdfLexer: unexpected '>' at offset ${startPos} (expected '>>' for dict end)`,
3987
+ offset: startPos,
3988
+ expected: "'>>' (dict end delimiter)",
3989
+ actual: "'>' (lone angle bracket)",
3990
+ data: this._data
3991
+ });
3919
3992
  }
3920
3993
  if (b === CH_LPAREN) return this.readLiteralString(startPos);
3921
3994
  if (b === CH_SLASH) return this.readName(startPos);
@@ -3930,7 +4003,7 @@ var PdfLexer = class {
3930
4003
  * `-.002`, `+.5`). Scientific notation is **not** permitted.
3931
4004
  */
3932
4005
  readNumber(startPos) {
3933
- const d = this.data;
4006
+ const d = this._data;
3934
4007
  let pos = startPos;
3935
4008
  let hasSign = false;
3936
4009
  let hasDot = false;
@@ -3974,10 +4047,10 @@ var PdfLexer = class {
3974
4047
  * parentheses.
3975
4048
  */
3976
4049
  readLiteralString(startPos) {
3977
- const d = this.data;
4050
+ const d = this._data;
3978
4051
  let pos = startPos + 1;
3979
4052
  let depth = 1;
3980
- let result = "";
4053
+ const parts = [];
3981
4054
  while (pos < this.len && depth > 0) {
3982
4055
  const c = d[pos];
3983
4056
  if (c === CH_BACKSLASH) {
@@ -3986,35 +4059,35 @@ var PdfLexer = class {
3986
4059
  const esc = d[pos];
3987
4060
  switch (esc) {
3988
4061
  case 110:
3989
- result += "\n";
4062
+ parts.push("\n");
3990
4063
  pos++;
3991
4064
  break;
3992
4065
  case 114:
3993
- result += "\r";
4066
+ parts.push("\r");
3994
4067
  pos++;
3995
4068
  break;
3996
4069
  case 116:
3997
- result += " ";
4070
+ parts.push(" ");
3998
4071
  pos++;
3999
4072
  break;
4000
4073
  case 98:
4001
- result += "\b";
4074
+ parts.push("\b");
4002
4075
  pos++;
4003
4076
  break;
4004
4077
  case 102:
4005
- result += "\f";
4078
+ parts.push("\f");
4006
4079
  pos++;
4007
4080
  break;
4008
4081
  case CH_LPAREN:
4009
- result += "(";
4082
+ parts.push("(");
4010
4083
  pos++;
4011
4084
  break;
4012
4085
  case CH_RPAREN:
4013
- result += ")";
4086
+ parts.push(")");
4014
4087
  pos++;
4015
4088
  break;
4016
4089
  case CH_BACKSLASH:
4017
- result += "\\";
4090
+ parts.push("\\");
4018
4091
  pos++;
4019
4092
  break;
4020
4093
  case WS_LF:
@@ -4036,9 +4109,9 @@ var PdfLexer = class {
4036
4109
  pos++;
4037
4110
  }
4038
4111
  }
4039
- result += String.fromCharCode(octal & 255);
4112
+ parts.push(String.fromCharCode(octal & 255));
4040
4113
  } else {
4041
- result += String.fromCharCode(esc);
4114
+ parts.push(String.fromCharCode(esc));
4042
4115
  pos++;
4043
4116
  }
4044
4117
  break;
@@ -4047,30 +4120,36 @@ var PdfLexer = class {
4047
4120
  }
4048
4121
  if (c === CH_LPAREN) {
4049
4122
  depth++;
4050
- result += "(";
4123
+ parts.push("(");
4051
4124
  pos++;
4052
4125
  continue;
4053
4126
  }
4054
4127
  if (c === CH_RPAREN) {
4055
4128
  depth--;
4056
- if (depth > 0) result += ")";
4129
+ if (depth > 0) parts.push(")");
4057
4130
  pos++;
4058
4131
  continue;
4059
4132
  }
4060
4133
  if (c === WS_CR) {
4061
- result += "\n";
4134
+ parts.push("\n");
4062
4135
  pos++;
4063
4136
  if (pos < this.len && d[pos] === WS_LF) pos++;
4064
4137
  continue;
4065
4138
  }
4066
- result += String.fromCharCode(c);
4139
+ parts.push(String.fromCharCode(c));
4067
4140
  pos++;
4068
4141
  }
4069
- if (depth !== 0) throw new Error(`PdfLexer: unterminated literal string starting at offset ${startPos}`);
4142
+ if (depth !== 0) throw new PdfParseError({
4143
+ message: `PdfLexer: unterminated literal string starting at offset ${startPos}`,
4144
+ offset: startPos,
4145
+ expected: "closing ')' for literal string",
4146
+ actual: "end of input",
4147
+ data: this._data
4148
+ });
4070
4149
  this.position = pos;
4071
4150
  return {
4072
4151
  type: TokenType$1.LiteralString,
4073
- value: result,
4152
+ value: parts.join(""),
4074
4153
  offset: startPos
4075
4154
  };
4076
4155
  }
@@ -4081,9 +4160,10 @@ var PdfLexer = class {
4081
4160
  * odd, a trailing `0` is assumed (per spec SS 7.3.4.3).
4082
4161
  */
4083
4162
  readHexString(startPos) {
4084
- const d = this.data;
4163
+ const d = this._data;
4085
4164
  let pos = startPos + 1;
4086
- let hex = "";
4165
+ const bytes = [];
4166
+ let hi = -1;
4087
4167
  while (pos < this.len) {
4088
4168
  const c = d[pos];
4089
4169
  if (c === CH_GT) {
@@ -4094,21 +4174,26 @@ var PdfLexer = class {
4094
4174
  pos++;
4095
4175
  continue;
4096
4176
  }
4097
- if (hexVal[c] === -1) throw new Error(`PdfLexer: invalid hex digit 0x${c.toString(16).padStart(2, "0")} at offset ${pos} in hex string starting at ${startPos}`);
4098
- hex += String.fromCharCode(c);
4177
+ const v = hexVal$1[c];
4178
+ if (v === -1) throw new PdfParseError({
4179
+ message: `PdfLexer: invalid hex digit 0x${c.toString(16).padStart(2, "0")} at offset ${pos} in hex string starting at ${startPos}`,
4180
+ offset: pos,
4181
+ expected: "hex digit (0-9, a-f, A-F)",
4182
+ actual: `0x${c.toString(16).padStart(2, "0")}`,
4183
+ data: this._data
4184
+ });
4185
+ if (hi === -1) hi = v;
4186
+ else {
4187
+ bytes.push(hi << 4 | v);
4188
+ hi = -1;
4189
+ }
4099
4190
  pos++;
4100
4191
  }
4101
- if (hex.length % 2 !== 0) hex += "0";
4102
- let result = "";
4103
- for (let i = 0; i < hex.length; i += 2) {
4104
- const hi = hexVal[hex.charCodeAt(i)];
4105
- const lo = hexVal[hex.charCodeAt(i + 1)];
4106
- result += String.fromCharCode(hi << 4 | lo);
4107
- }
4192
+ if (hi !== -1) bytes.push(hi << 4);
4108
4193
  this.position = pos;
4109
4194
  return {
4110
4195
  type: TokenType$1.HexString,
4111
- value: result,
4196
+ value: String.fromCharCode.apply(null, bytes),
4112
4197
  offset: startPos
4113
4198
  };
4114
4199
  }
@@ -4119,28 +4204,40 @@ var PdfLexer = class {
4119
4204
  * **includes** the leading `/`.
4120
4205
  */
4121
4206
  readName(startPos) {
4122
- const d = this.data;
4207
+ const d = this._data;
4123
4208
  let pos = startPos + 1;
4124
- let name = "/";
4209
+ const parts = ["/"];
4125
4210
  while (pos < this.len) {
4126
4211
  const c = d[pos];
4127
4212
  if (isWhitespace[c] || isDelimiter[c]) break;
4128
4213
  if (c === CH_HASH) {
4129
- if (pos + 2 >= this.len) throw new Error(`PdfLexer: incomplete #XX escape in name at offset ${pos}`);
4130
- const hi = hexVal[d[pos + 1]];
4131
- const lo = hexVal[d[pos + 2]];
4132
- if (hi === -1 || lo === -1) throw new Error(`PdfLexer: invalid #XX escape in name at offset ${pos}`);
4133
- name += String.fromCharCode(hi << 4 | lo);
4214
+ if (pos + 2 >= this.len) throw new PdfParseError({
4215
+ message: `PdfLexer: incomplete #XX escape in name at offset ${pos}`,
4216
+ offset: pos,
4217
+ expected: "two hex digits after # in name",
4218
+ actual: "end of input",
4219
+ data: this._data
4220
+ });
4221
+ const hi = hexVal$1[d[pos + 1]];
4222
+ const lo = hexVal$1[d[pos + 2]];
4223
+ if (hi === -1 || lo === -1) throw new PdfParseError({
4224
+ message: `PdfLexer: invalid #XX escape in name at offset ${pos}`,
4225
+ offset: pos,
4226
+ expected: "valid hex digits after # in name",
4227
+ actual: `#${String.fromCharCode(d[pos + 1])}${String.fromCharCode(d[pos + 2])}`,
4228
+ data: this._data
4229
+ });
4230
+ parts.push(String.fromCharCode(hi << 4 | lo));
4134
4231
  pos += 3;
4135
4232
  continue;
4136
4233
  }
4137
- name += String.fromCharCode(c);
4234
+ parts.push(String.fromCharCode(c));
4138
4235
  pos++;
4139
4236
  }
4140
4237
  this.position = pos;
4141
4238
  return {
4142
4239
  type: TokenType$1.Name,
4143
- value: name,
4240
+ value: parts.join(""),
4144
4241
  offset: startPos
4145
4242
  };
4146
4243
  }
@@ -4151,7 +4248,7 @@ var PdfLexer = class {
4151
4248
  * available for callers that want to preserve them.
4152
4249
  */
4153
4250
  readComment(startPos) {
4154
- const d = this.data;
4251
+ const d = this._data;
4155
4252
  let pos = startPos + 1;
4156
4253
  const begin = pos;
4157
4254
  while (pos < this.len) {
@@ -4176,7 +4273,7 @@ var PdfLexer = class {
4176
4273
  * handle them.
4177
4274
  */
4178
4275
  readKeyword(startPos) {
4179
- const d = this.data;
4276
+ const d = this._data;
4180
4277
  let pos = startPos;
4181
4278
  while (pos < this.len) {
4182
4279
  const c = d[pos];
@@ -4255,10 +4352,7 @@ var PdfLexer = class {
4255
4352
  * because it avoids the per-call overhead of the streaming decoder.
4256
4353
  */
4257
4354
  bytesToAscii(from, to) {
4258
- const d = this.data;
4259
- let s = "";
4260
- for (let i = from; i < to; i++) s += String.fromCharCode(d[i]);
4261
- return s;
4355
+ return String.fromCharCode.apply(null, this._data.subarray(from, to));
4262
4356
  }
4263
4357
  };
4264
4358
 
@@ -4331,13 +4425,31 @@ var PdfObjectParser = class {
4331
4425
  */
4332
4426
  parseIndirectObject() {
4333
4427
  const objNumToken = this.lexer.nextToken();
4334
- if (objNumToken.type !== TokenType$1.Number || !Number.isInteger(objNumToken.value)) throw new Error(`PdfObjectParser.parseIndirectObject: expected integer object number at offset ${objNumToken.offset}, got ${TokenType$1[objNumToken.type]} (${String(objNumToken.value)})`);
4428
+ if (objNumToken.type !== TokenType$1.Number || !Number.isInteger(objNumToken.value)) throw new PdfParseError({
4429
+ message: `PdfObjectParser.parseIndirectObject: expected integer object number at offset ${objNumToken.offset}, got ${TokenType$1[objNumToken.type]} (${String(objNumToken.value)})`,
4430
+ offset: objNumToken.offset,
4431
+ expected: "integer object number",
4432
+ actual: `${TokenType$1[objNumToken.type]} (${String(objNumToken.value)})`,
4433
+ data: this.lexer.rawData
4434
+ });
4335
4435
  const objNum = objNumToken.value;
4336
4436
  const genNumToken = this.lexer.nextToken();
4337
- if (genNumToken.type !== TokenType$1.Number || !Number.isInteger(genNumToken.value)) throw new Error(`PdfObjectParser.parseIndirectObject: expected integer generation number at offset ${genNumToken.offset}, got ${TokenType$1[genNumToken.type]} (${String(genNumToken.value)})`);
4437
+ if (genNumToken.type !== TokenType$1.Number || !Number.isInteger(genNumToken.value)) throw new PdfParseError({
4438
+ message: `PdfObjectParser.parseIndirectObject: expected integer generation number at offset ${genNumToken.offset}, got ${TokenType$1[genNumToken.type]} (${String(genNumToken.value)})`,
4439
+ offset: genNumToken.offset,
4440
+ expected: "integer generation number",
4441
+ actual: `${TokenType$1[genNumToken.type]} (${String(genNumToken.value)})`,
4442
+ data: this.lexer.rawData
4443
+ });
4338
4444
  const genNum = genNumToken.value;
4339
4445
  const objKw = this.lexer.nextToken();
4340
- if (objKw.type !== TokenType$1.ObjKeyword) throw new Error(`PdfObjectParser.parseIndirectObject: expected 'obj' keyword at offset ${objKw.offset}, got ${TokenType$1[objKw.type]} (${String(objKw.value)})`);
4446
+ if (objKw.type !== TokenType$1.ObjKeyword) throw new PdfParseError({
4447
+ message: `PdfObjectParser.parseIndirectObject: expected 'obj' keyword at offset ${objKw.offset}, got ${TokenType$1[objKw.type]} (${String(objKw.value)})`,
4448
+ offset: objKw.offset,
4449
+ expected: "'obj' keyword",
4450
+ actual: `${TokenType$1[objKw.type]} (${String(objKw.value)})`,
4451
+ data: this.lexer.rawData
4452
+ });
4341
4453
  return this.parseIndirectObjectBody(objNum, genNum);
4342
4454
  }
4343
4455
  /**
@@ -4382,8 +4494,20 @@ var PdfObjectParser = class {
4382
4494
  case TokenType$1.Name: return PdfName.of(token.value);
4383
4495
  case TokenType$1.ArrayStart: return this.parseArray();
4384
4496
  case TokenType$1.DictStart: return this.parseDictOrStream();
4385
- case TokenType$1.EOF: throw new Error(`PdfObjectParser: unexpected end of input at offset ${token.offset}`);
4386
- default: throw new Error(`PdfObjectParser: unexpected token ${TokenType$1[token.type]} (${String(token.value)}) at offset ${token.offset}`);
4497
+ case TokenType$1.EOF: throw new PdfParseError({
4498
+ message: `PdfObjectParser: unexpected end of input at offset ${token.offset}`,
4499
+ offset: token.offset,
4500
+ expected: "a PDF object (number, string, name, array, dict, etc.)",
4501
+ actual: "end of input",
4502
+ data: this.lexer.rawData
4503
+ });
4504
+ default: throw new PdfParseError({
4505
+ message: `PdfObjectParser: unexpected token ${TokenType$1[token.type]} (${String(token.value)}) at offset ${token.offset}`,
4506
+ offset: token.offset,
4507
+ expected: "a PDF object (number, string, name, array, dict, etc.)",
4508
+ actual: `${TokenType$1[token.type]} (${String(token.value)})`,
4509
+ data: this.lexer.rawData
4510
+ });
4387
4511
  }
4388
4512
  }
4389
4513
  /**
@@ -4429,7 +4553,13 @@ var PdfObjectParser = class {
4429
4553
  if (this.lexer.peekToken().type === TokenType$1.StreamKeyword) finalObject = this.readStream(object);
4430
4554
  }
4431
4555
  const endToken = this.lexer.nextToken();
4432
- if (endToken.type !== TokenType$1.EndObjKeyword) throw new Error(`PdfObjectParser: expected 'endobj' for object ${objNum} ${genNum} at offset ${endToken.offset}, got ${TokenType$1[endToken.type]} (${String(endToken.value)})`);
4556
+ if (endToken.type !== TokenType$1.EndObjKeyword) throw new PdfParseError({
4557
+ message: `PdfObjectParser: expected 'endobj' for object ${objNum} ${genNum} at offset ${endToken.offset}, got ${TokenType$1[endToken.type]} (${String(endToken.value)})`,
4558
+ offset: endToken.offset,
4559
+ expected: `'endobj' keyword for object ${objNum} ${genNum}`,
4560
+ actual: `${TokenType$1[endToken.type]} (${String(endToken.value)})`,
4561
+ data: this.lexer.rawData
4562
+ });
4433
4563
  this.registry.registerWithRef(ref, finalObject);
4434
4564
  return {
4435
4565
  ref,
@@ -4449,7 +4579,13 @@ var PdfObjectParser = class {
4449
4579
  this.lexer.nextToken();
4450
4580
  break;
4451
4581
  }
4452
- if (peek.type === TokenType$1.EOF) throw new Error(`PdfObjectParser: unterminated array at offset ${peek.offset}`);
4582
+ if (peek.type === TokenType$1.EOF) throw new PdfParseError({
4583
+ message: `PdfObjectParser: unterminated array at offset ${peek.offset}`,
4584
+ offset: peek.offset,
4585
+ expected: "']' to close array",
4586
+ actual: "end of input",
4587
+ data: this.lexer.rawData
4588
+ });
4453
4589
  items.push(this.parseObject());
4454
4590
  }
4455
4591
  return new PdfArray(items);
@@ -4478,9 +4614,21 @@ var PdfObjectParser = class {
4478
4614
  this.lexer.nextToken();
4479
4615
  break;
4480
4616
  }
4481
- if (peek.type === TokenType$1.EOF) throw new Error(`PdfObjectParser: unterminated dictionary at offset ${peek.offset}`);
4617
+ if (peek.type === TokenType$1.EOF) throw new PdfParseError({
4618
+ message: `PdfObjectParser: unterminated dictionary at offset ${peek.offset}`,
4619
+ offset: peek.offset,
4620
+ expected: "'>>' to close dictionary",
4621
+ actual: "end of input",
4622
+ data: this.lexer.rawData
4623
+ });
4482
4624
  const keyToken = this.lexer.nextToken();
4483
- if (keyToken.type !== TokenType$1.Name) throw new Error(`PdfObjectParser: expected name as dictionary key at offset ${keyToken.offset}, got ${TokenType$1[keyToken.type]} (${String(keyToken.value)})`);
4625
+ if (keyToken.type !== TokenType$1.Name) throw new PdfParseError({
4626
+ message: `PdfObjectParser: expected name as dictionary key at offset ${keyToken.offset}, got ${TokenType$1[keyToken.type]} (${String(keyToken.value)})`,
4627
+ offset: keyToken.offset,
4628
+ expected: "name token as dictionary key",
4629
+ actual: `${TokenType$1[keyToken.type]} (${String(keyToken.value)})`,
4630
+ data: this.lexer.rawData
4631
+ });
4484
4632
  const key = keyToken.value;
4485
4633
  const value = this.parseObject();
4486
4634
  dict.set(key, value);
@@ -4499,13 +4647,25 @@ var PdfObjectParser = class {
4499
4647
  */
4500
4648
  readStream(dict) {
4501
4649
  const streamKw = this.lexer.nextToken();
4502
- if (streamKw.type !== TokenType$1.StreamKeyword) throw new Error(`PdfObjectParser.readStream: expected 'stream' keyword at offset ${streamKw.offset}, got ${TokenType$1[streamKw.type]}`);
4650
+ if (streamKw.type !== TokenType$1.StreamKeyword) throw new PdfParseError({
4651
+ message: `PdfObjectParser.readStream: expected 'stream' keyword at offset ${streamKw.offset}, got ${TokenType$1[streamKw.type]}`,
4652
+ offset: streamKw.offset,
4653
+ expected: "'stream' keyword",
4654
+ actual: `${TokenType$1[streamKw.type]}`,
4655
+ data: this.lexer.rawData
4656
+ });
4503
4657
  this.skipStreamEol();
4504
4658
  const length = this.resolveStreamLength(dict);
4505
4659
  const data = this.lexer.readStreamData(length);
4506
4660
  this.skipEndstreamWhitespace();
4507
4661
  const endKw = this.lexer.nextToken();
4508
- if (endKw.type !== TokenType$1.EndStreamKeyword) throw new Error(`PdfObjectParser.readStream: expected 'endstream' keyword at offset ${endKw.offset}, got ${TokenType$1[endKw.type]} (${String(endKw.value)})`);
4662
+ if (endKw.type !== TokenType$1.EndStreamKeyword) throw new PdfParseError({
4663
+ message: `PdfObjectParser.readStream: expected 'endstream' keyword at offset ${endKw.offset}, got ${TokenType$1[endKw.type]} (${String(endKw.value)})`,
4664
+ offset: endKw.offset,
4665
+ expected: "'endstream' keyword",
4666
+ actual: `${TokenType$1[endKw.type]} (${String(endKw.value)})`,
4667
+ data: this.lexer.rawData
4668
+ });
4509
4669
  return new PdfStream(dict, data);
4510
4670
  }
4511
4671
  /**
@@ -4550,18 +4710,42 @@ var PdfObjectParser = class {
4550
4710
  */
4551
4711
  resolveStreamLength(dict) {
4552
4712
  const lengthObj = dict.get("/Length");
4553
- if (lengthObj === void 0) throw new Error("PdfObjectParser.resolveStreamLength: stream dictionary is missing /Length");
4713
+ if (lengthObj === void 0) throw new PdfParseError({
4714
+ message: "PdfObjectParser.resolveStreamLength: stream dictionary is missing /Length",
4715
+ offset: this.lexer.position,
4716
+ expected: "/Length entry in stream dictionary",
4717
+ actual: "no /Length entry",
4718
+ data: this.lexer.rawData
4719
+ });
4554
4720
  if (lengthObj.kind === "number") return lengthObj.value;
4555
4721
  if (lengthObj.kind === "ref") {
4556
4722
  const ref = lengthObj;
4557
4723
  const resolved = this.registry.resolve(ref);
4558
4724
  if (resolved !== void 0) {
4559
- if (resolved.kind !== "number") throw new Error(`PdfObjectParser.resolveStreamLength: /Length reference ${ref.objectNumber} ${ref.generationNumber} R resolved to ${resolved.kind}, expected number`);
4725
+ if (resolved.kind !== "number") throw new PdfParseError({
4726
+ message: `PdfObjectParser.resolveStreamLength: /Length reference ${ref.objectNumber} ${ref.generationNumber} R resolved to ${resolved.kind}, expected number`,
4727
+ offset: this.lexer.position,
4728
+ expected: "number for /Length reference",
4729
+ actual: `${resolved.kind}`,
4730
+ data: this.lexer.rawData
4731
+ });
4560
4732
  return resolved.value;
4561
4733
  }
4562
- throw new Error(`PdfObjectParser.resolveStreamLength: /Length reference ${ref.objectNumber} ${ref.generationNumber} R is not yet resolved in the registry. Parse the referenced object first.`);
4734
+ throw new PdfParseError({
4735
+ message: `PdfObjectParser.resolveStreamLength: /Length reference ${ref.objectNumber} ${ref.generationNumber} R is not yet resolved in the registry. Parse the referenced object first.`,
4736
+ offset: this.lexer.position,
4737
+ expected: "resolved /Length reference",
4738
+ actual: `unresolved reference ${ref.objectNumber} ${ref.generationNumber} R`,
4739
+ data: this.lexer.rawData
4740
+ });
4563
4741
  }
4564
- throw new Error(`PdfObjectParser.resolveStreamLength: /Length must be a number or indirect reference, got ${lengthObj.kind}`);
4742
+ throw new PdfParseError({
4743
+ message: `PdfObjectParser.resolveStreamLength: /Length must be a number or indirect reference, got ${lengthObj.kind}`,
4744
+ offset: this.lexer.position,
4745
+ expected: "number or indirect reference for /Length",
4746
+ actual: `${lengthObj.kind}`,
4747
+ data: this.lexer.rawData
4748
+ });
4565
4749
  }
4566
4750
  };
4567
4751
 
@@ -4642,10 +4826,10 @@ async function tryLoadLibdeflate() {
4642
4826
  if (libdeflateAttempted) return libdeflateEngine;
4643
4827
  libdeflateAttempted = true;
4644
4828
  try {
4645
- const { LibdeflateWasm: LibdeflateCtor, initDeflateWasm } = await import("./libdeflateWasm-CRFwmrSl.mjs").then((n) => n.r);
4829
+ const { LibdeflateWasm: LibdeflateCtor, initDeflateWasm } = await import("./libdeflateWasm-DlHgU5oy.mjs").then((n) => n.r);
4646
4830
  let customBytes;
4647
4831
  try {
4648
- const { getWasmLoaderConfig } = await import("./loader-CZMj0gBy.mjs");
4832
+ const { getWasmLoaderConfig } = await import("./loader-CQfoGFp9.mjs");
4649
4833
  customBytes = getWasmLoaderConfig().moduleBytes?.["libdeflate"];
4650
4834
  } catch {}
4651
4835
  await initDeflateWasm(customBytes);
@@ -4763,9 +4947,19 @@ function stringToLatin1Bytes(str) {
4763
4947
  */
4764
4948
  function extractTrailer(dict) {
4765
4949
  const sizeVal = numVal$2(dict.get("/Size"));
4766
- if (sizeVal === void 0) throw new Error("Invalid PDF: trailer dictionary missing /Size entry");
4950
+ if (sizeVal === void 0) throw new PdfParseError({
4951
+ message: "Invalid PDF: trailer dictionary missing /Size entry",
4952
+ offset: 0,
4953
+ expected: "/Size entry in trailer dictionary",
4954
+ actual: "no /Size entry"
4955
+ });
4767
4956
  const rootRef = refVal(dict.get("/Root"));
4768
- if (rootRef === void 0) throw new Error("Invalid PDF: trailer dictionary missing /Root entry");
4957
+ if (rootRef === void 0) throw new PdfParseError({
4958
+ message: "Invalid PDF: trailer dictionary missing /Root entry",
4959
+ offset: 0,
4960
+ expected: "/Root entry in trailer dictionary",
4961
+ actual: "no /Root entry"
4962
+ });
4769
4963
  const trailer = {
4770
4964
  size: sizeVal,
4771
4965
  rootRef
@@ -4804,7 +4998,12 @@ async function decodeStream$1(streamData, dict) {
4804
4998
  const arr = filter;
4805
4999
  if (arr.length > 0 && arr.items[0].kind === "name") filterName = arr.items[0].value;
4806
5000
  }
4807
- if (filterName !== "/FlateDecode") throw new Error(`Unsupported xref stream filter: ${filterName ?? "unknown"}. Only /FlateDecode is supported for cross-reference streams.`);
5001
+ if (filterName !== "/FlateDecode") throw new PdfParseError({
5002
+ message: `Unsupported xref stream filter: ${filterName ?? "unknown"}. Only /FlateDecode is supported for cross-reference streams.`,
5003
+ offset: 0,
5004
+ expected: "/FlateDecode filter",
5005
+ actual: `${filterName ?? "unknown"} filter`
5006
+ });
4808
5007
  let decompressed = await decompress(streamData);
4809
5008
  const decodeParms = dict.get("/DecodeParms");
4810
5009
  if (decodeParms !== void 0 && decodeParms.kind === "dict") {
@@ -4938,11 +5137,30 @@ var XrefParser = class {
4938
5137
  const startPos = this.data.length - searchWindow;
4939
5138
  const tail = TEXT_DECODER$1.decode(this.data.subarray(startPos, this.data.length));
4940
5139
  const idx = tail.lastIndexOf("startxref");
4941
- if (idx === -1) throw new Error("Invalid PDF: could not find \"startxref\" marker in the last 2048 bytes. The file may be truncated or corrupt.");
4942
- const match = tail.substring(idx + 9).trim().match(/^(\d+)/);
4943
- if (!match) throw new Error("Invalid PDF: \"startxref\" found but no valid offset follows it.");
5140
+ if (idx === -1) throw new PdfParseError({
5141
+ message: "Invalid PDF: could not find \"startxref\" marker in the last 2048 bytes. The file may be truncated or corrupt.",
5142
+ offset: startPos,
5143
+ expected: "\"startxref\" marker near end of file",
5144
+ actual: "no \"startxref\" found",
5145
+ data: this.data
5146
+ });
5147
+ const afterKeyword = tail.substring(idx + 9).trim();
5148
+ const match = afterKeyword.match(/^(\d+)/);
5149
+ if (!match) throw new PdfParseError({
5150
+ message: "Invalid PDF: \"startxref\" found but no valid offset follows it.",
5151
+ offset: startPos + idx,
5152
+ expected: "decimal offset after \"startxref\"",
5153
+ actual: `"${afterKeyword.substring(0, 20)}"`,
5154
+ data: this.data
5155
+ });
4944
5156
  const offset = parseInt(match[1], 10);
4945
- if (offset < 0 || offset >= this.data.length) throw new Error(`Invalid PDF: startxref offset ${offset} is out of range (file size: ${this.data.length}).`);
5157
+ if (offset < 0 || offset >= this.data.length) throw new PdfParseError({
5158
+ message: `Invalid PDF: startxref offset ${offset} is out of range (file size: ${this.data.length}).`,
5159
+ offset: startPos + idx,
5160
+ expected: `offset in range [0, ${this.data.length})`,
5161
+ actual: `${offset}`,
5162
+ data: this.data
5163
+ });
4946
5164
  return offset;
4947
5165
  }
4948
5166
  /**
@@ -4995,7 +5213,13 @@ var XrefParser = class {
4995
5213
  const prevVal = numVal$2(trailerDict.get("/Prev"));
4996
5214
  currentOffset = prevVal !== void 0 && prevVal >= 0 ? prevVal : void 0;
4997
5215
  }
4998
- if (primaryTrailer === void 0) throw new Error("Invalid PDF: could not extract a valid trailer from the cross-reference structure.");
5216
+ if (primaryTrailer === void 0) throw new PdfParseError({
5217
+ message: "Invalid PDF: could not extract a valid trailer from the cross-reference structure.",
5218
+ offset: startOffset,
5219
+ expected: "valid trailer dictionary in cross-reference structure",
5220
+ actual: "no valid trailer found",
5221
+ data: this.data
5222
+ });
4999
5223
  return {
5000
5224
  entries,
5001
5225
  trailer: primaryTrailer
@@ -5022,40 +5246,82 @@ var XrefParser = class {
5022
5246
  parseTraditionalXref(offset) {
5023
5247
  const entries = [];
5024
5248
  let pos = offset;
5025
- const xrefTag = TEXT_DECODER$1.decode(this.data.subarray(pos, pos + 4));
5026
- if (xrefTag !== "xref") throw new Error(`Invalid PDF: expected "xref" keyword at offset ${offset}, found "${xrefTag}".`);
5249
+ if (!this.isTraditionalXref(pos)) {
5250
+ const xrefTag = TEXT_DECODER$1.decode(this.data.subarray(pos, pos + 4));
5251
+ throw new PdfParseError({
5252
+ message: `Invalid PDF: expected "xref" keyword at offset ${offset}, found "${xrefTag}".`,
5253
+ offset,
5254
+ expected: "\"xref\" keyword",
5255
+ actual: `"${xrefTag}"`,
5256
+ data: this.data
5257
+ });
5258
+ }
5027
5259
  pos += 4;
5028
5260
  pos = this.skipWhitespaceAt(pos);
5029
5261
  while (pos < this.data.length) {
5030
- if (TEXT_DECODER$1.decode(this.data.subarray(pos, Math.min(pos + 7, this.data.length))).startsWith("trailer")) break;
5262
+ if (this.matchesBytes(pos, 116, 114, 97, 105, 108, 101, 114)) break;
5031
5263
  const headerLine = this.readLineAt(pos);
5032
5264
  const headerMatch = headerLine.text.trim().match(/^(\d+)\s+(\d+)/);
5033
- if (!headerMatch) throw new Error(`Invalid PDF: malformed xref subsection header at offset ${pos}: "${headerLine.text.trim()}"`);
5265
+ if (!headerMatch) throw new PdfParseError({
5266
+ message: `Invalid PDF: malformed xref subsection header at offset ${pos}: "${headerLine.text.trim()}"`,
5267
+ offset: pos,
5268
+ expected: "xref subsection header \"firstObjNum count\"",
5269
+ actual: `"${headerLine.text.trim()}"`,
5270
+ data: this.data
5271
+ });
5034
5272
  const firstObjNum = parseInt(headerMatch[1], 10);
5035
5273
  const count = parseInt(headerMatch[2], 10);
5036
5274
  pos = headerLine.nextPos;
5037
5275
  for (let i = 0; i < count; i++) {
5038
5276
  const objectNumber = firstObjNum + i;
5039
- const entryText = this.readXrefEntryAt(pos);
5040
- const entryMatch = entryText.text.trim().match(/^(\d{10})\s+(\d{5})\s+([fn])/);
5041
- if (!entryMatch) throw new Error(`Invalid PDF: malformed xref entry at offset ${pos} for object ${objectNumber}: "${entryText.text.trim()}"`);
5042
- const entryOffset = parseInt(entryMatch[1], 10);
5043
- const gen = parseInt(entryMatch[2], 10);
5044
- const marker = entryMatch[3];
5045
- entries.push({
5046
- objectNumber,
5047
- generationNumber: gen,
5048
- offset: entryOffset,
5049
- type: marker === "n" ? "in-use" : "free"
5050
- });
5051
- pos = entryText.nextPos;
5277
+ const parsed = this.parseXrefEntryDirect(pos);
5278
+ if (parsed) {
5279
+ entries.push({
5280
+ objectNumber,
5281
+ generationNumber: parsed.gen,
5282
+ offset: parsed.offset,
5283
+ type: parsed.type
5284
+ });
5285
+ pos = parsed.nextPos;
5286
+ } else {
5287
+ const entryText = this.readXrefEntryAt(pos);
5288
+ const entryMatch = entryText.text.trim().match(/^(\d{10})\s+(\d{5})\s+([fn])/);
5289
+ if (!entryMatch) throw new PdfParseError({
5290
+ message: `Invalid PDF: malformed xref entry at offset ${pos} for object ${objectNumber}: "${entryText.text.trim()}"`,
5291
+ offset: pos,
5292
+ expected: "xref entry \"OOOOOOOOOO GGGGG f/n\"",
5293
+ actual: `"${entryText.text.trim()}"`,
5294
+ data: this.data
5295
+ });
5296
+ entries.push({
5297
+ objectNumber,
5298
+ generationNumber: parseInt(entryMatch[2], 10),
5299
+ offset: parseInt(entryMatch[1], 10),
5300
+ type: entryMatch[3] === "n" ? "in-use" : "free"
5301
+ });
5302
+ pos = entryText.nextPos;
5303
+ }
5052
5304
  }
5053
5305
  }
5054
- const trailerTag = TEXT_DECODER$1.decode(this.data.subarray(pos, pos + 7));
5055
- if (trailerTag !== "trailer") throw new Error(`Invalid PDF: expected "trailer" keyword at offset ${pos}, found "${trailerTag}".`);
5306
+ if (!this.matchesBytes(pos, 116, 114, 97, 105, 108, 101, 114)) {
5307
+ const trailerTag = TEXT_DECODER$1.decode(this.data.subarray(pos, pos + 7));
5308
+ throw new PdfParseError({
5309
+ message: `Invalid PDF: expected "trailer" keyword at offset ${pos}, found "${trailerTag}".`,
5310
+ offset: pos,
5311
+ expected: "\"trailer\" keyword",
5312
+ actual: `"${trailerTag}"`,
5313
+ data: this.data
5314
+ });
5315
+ }
5056
5316
  pos += 7;
5057
5317
  const trailerObj = this.objectParser.parseObjectAt(pos);
5058
- if (trailerObj.kind !== "dict") throw new Error(`Invalid PDF: expected dictionary after "trailer" keyword at offset ${pos}, got ${trailerObj.kind}.`);
5318
+ if (trailerObj.kind !== "dict") throw new PdfParseError({
5319
+ message: `Invalid PDF: expected dictionary after "trailer" keyword at offset ${pos}, got ${trailerObj.kind}.`,
5320
+ offset: pos,
5321
+ expected: "dictionary after \"trailer\" keyword",
5322
+ actual: `${trailerObj.kind}`,
5323
+ data: this.data
5324
+ });
5059
5325
  return {
5060
5326
  entries,
5061
5327
  trailerDict: trailerObj
@@ -5074,22 +5340,58 @@ var XrefParser = class {
5074
5340
  */
5075
5341
  async parseXrefStream(offset) {
5076
5342
  const { object } = this.objectParser.parseIndirectObjectAt(offset);
5077
- if (object.kind !== "stream") throw new Error(`Invalid PDF: expected stream object at offset ${offset} for xref stream, got ${object.kind}.`);
5343
+ if (object.kind !== "stream") throw new PdfParseError({
5344
+ message: `Invalid PDF: expected stream object at offset ${offset} for xref stream, got ${object.kind}.`,
5345
+ offset,
5346
+ expected: "stream object for xref stream",
5347
+ actual: `${object.kind}`,
5348
+ data: this.data
5349
+ });
5078
5350
  const stream = object;
5079
5351
  const dict = stream.dict;
5080
5352
  const typeObj = dict.get("/Type");
5081
- if (typeObj === void 0 || typeObj.kind !== "name" || typeObj.value !== "/XRef") throw new Error(`Invalid PDF: cross-reference stream at offset ${offset} does not have /Type /XRef.`);
5353
+ if (typeObj === void 0 || typeObj.kind !== "name" || typeObj.value !== "/XRef") throw new PdfParseError({
5354
+ message: `Invalid PDF: cross-reference stream at offset ${offset} does not have /Type /XRef.`,
5355
+ offset,
5356
+ expected: "/Type /XRef in cross-reference stream dictionary",
5357
+ actual: typeObj ? `${typeObj.kind}` : "no /Type entry",
5358
+ data: this.data
5359
+ });
5082
5360
  const wObj = dict.get("/W");
5083
- if (wObj === void 0 || wObj.kind !== "array") throw new Error("Invalid PDF: cross-reference stream missing /W (field widths) array.");
5361
+ if (wObj === void 0 || wObj.kind !== "array") throw new PdfParseError({
5362
+ message: "Invalid PDF: cross-reference stream missing /W (field widths) array.",
5363
+ offset,
5364
+ expected: "/W array in cross-reference stream",
5365
+ actual: wObj ? `${wObj.kind}` : "no /W entry",
5366
+ data: this.data
5367
+ });
5084
5368
  const wArr = wObj;
5085
- if (wArr.length < 3) throw new Error("Invalid PDF: cross-reference stream /W array must have at least 3 elements.");
5369
+ if (wArr.length < 3) throw new PdfParseError({
5370
+ message: "Invalid PDF: cross-reference stream /W array must have at least 3 elements.",
5371
+ offset,
5372
+ expected: "/W array with at least 3 elements",
5373
+ actual: `/W array with ${wArr.length} element(s)`,
5374
+ data: this.data
5375
+ });
5086
5376
  const w0 = numVal$2(wArr.items[0]) ?? 0;
5087
5377
  const w1 = numVal$2(wArr.items[1]) ?? 0;
5088
5378
  const w2 = numVal$2(wArr.items[2]) ?? 0;
5089
5379
  const entryWidth = w0 + w1 + w2;
5090
- if (entryWidth === 0) throw new Error("Invalid PDF: cross-reference stream /W widths sum to 0.");
5380
+ if (entryWidth === 0) throw new PdfParseError({
5381
+ message: "Invalid PDF: cross-reference stream /W widths sum to 0.",
5382
+ offset,
5383
+ expected: "non-zero sum of /W widths",
5384
+ actual: "0",
5385
+ data: this.data
5386
+ });
5091
5387
  const size = numVal$2(dict.get("/Size"));
5092
- if (size === void 0) throw new Error("Invalid PDF: cross-reference stream missing /Size.");
5388
+ if (size === void 0) throw new PdfParseError({
5389
+ message: "Invalid PDF: cross-reference stream missing /Size.",
5390
+ offset,
5391
+ expected: "/Size entry in cross-reference stream",
5392
+ actual: "no /Size entry",
5393
+ data: this.data
5394
+ });
5093
5395
  let subsections;
5094
5396
  const indexObj = dict.get("/Index");
5095
5397
  if (indexObj !== void 0 && indexObj.kind === "array") {
@@ -5165,24 +5467,50 @@ var XrefParser = class {
5165
5467
  */
5166
5468
  rebuildXrefFromScan() {
5167
5469
  const entries = /* @__PURE__ */ new Map();
5168
- const fileText = TEXT_DECODER$1.decode(this.data);
5169
- const objPattern = /(\d+)\s+(\d+)\s+obj\b/g;
5170
- let match;
5171
- while ((match = objPattern.exec(fileText)) !== null) {
5172
- const objectNumber = parseInt(match[1], 10);
5173
- const gen = parseInt(match[2], 10);
5174
- const offset = match.index;
5470
+ const d = this.data;
5471
+ const len = d.length;
5472
+ for (let i = 0; i < len - 2; i++) {
5473
+ if (d[i] !== 111 || d[i + 1] !== 98 || d[i + 2] !== 106) continue;
5474
+ if (i + 3 < len) {
5475
+ const after = d[i + 3];
5476
+ if (after > 32 && after !== 37 && after !== 40 && after !== 41 && after !== 47 && after !== 60 && after !== 62 && after !== 91 && after !== 93 && after !== 123 && after !== 125) continue;
5477
+ }
5478
+ let j = i - 1;
5479
+ while (j >= 0 && (d[j] === 32 || d[j] === 10 || d[j] === 13 || d[j] === 9 || d[j] === 0)) j--;
5480
+ const genEnd = j + 1;
5481
+ while (j >= 0 && d[j] >= 48 && d[j] <= 57) j--;
5482
+ const genStart = j + 1;
5483
+ if (genStart >= genEnd) continue;
5484
+ while (j >= 0 && (d[j] === 32 || d[j] === 10 || d[j] === 13 || d[j] === 9 || d[j] === 0)) j--;
5485
+ const objEnd = j + 1;
5486
+ while (j >= 0 && d[j] >= 48 && d[j] <= 57) j--;
5487
+ const objStart = j + 1;
5488
+ if (objStart >= objEnd) continue;
5489
+ let objectNumber = 0;
5490
+ for (let k = objStart; k < objEnd; k++) objectNumber = objectNumber * 10 + (d[k] - 48);
5491
+ let gen = 0;
5492
+ for (let k = genStart; k < genEnd; k++) gen = gen * 10 + (d[k] - 48);
5175
5493
  entries.set(objectNumber, {
5176
5494
  objectNumber,
5177
5495
  generationNumber: gen,
5178
- offset,
5496
+ offset: objStart,
5179
5497
  type: "in-use"
5180
5498
  });
5181
5499
  }
5182
- if (entries.size === 0) throw new Error("Invalid PDF: could not find any indirect objects during recovery scan. The file may not be a valid PDF.");
5500
+ if (entries.size === 0) throw new PdfParseError({
5501
+ message: "Invalid PDF: could not find any indirect objects during recovery scan. The file may not be a valid PDF.",
5502
+ offset: 0,
5503
+ expected: "at least one \"N G obj\" pattern in file",
5504
+ actual: "no indirect objects found",
5505
+ data: this.data
5506
+ });
5183
5507
  let rootRef;
5184
5508
  let infoRef;
5185
- const trailerIdx = fileText.lastIndexOf("trailer");
5509
+ let trailerIdx = -1;
5510
+ for (let i = len - 7; i >= 0; i--) if (d[i] === 116 && d[i + 1] === 114 && d[i + 2] === 97 && d[i + 3] === 105 && d[i + 4] === 108 && d[i + 5] === 101 && d[i + 6] === 114) {
5511
+ trailerIdx = i;
5512
+ break;
5513
+ }
5186
5514
  if (trailerIdx !== -1) try {
5187
5515
  const trailerObj = this.objectParser.parseObjectAt(trailerIdx + 7);
5188
5516
  if (trailerObj.kind === "dict") {
@@ -5202,7 +5530,13 @@ var XrefParser = class {
5202
5530
  }
5203
5531
  }
5204
5532
  } catch {}
5205
- if (rootRef === void 0) throw new Error("Invalid PDF: recovery scan could not locate the document catalog (/Root). The file appears to be severely corrupt.");
5533
+ if (rootRef === void 0) throw new PdfParseError({
5534
+ message: "Invalid PDF: recovery scan could not locate the document catalog (/Root). The file appears to be severely corrupt.",
5535
+ offset: 0,
5536
+ expected: "document catalog (/Type /Catalog) in recovery scan",
5537
+ actual: "no /Root or /Catalog found",
5538
+ data: this.data
5539
+ });
5206
5540
  const trailer = {
5207
5541
  size: (entries.size > 0 ? entries.keys().reduce((max, n) => Math.max(max, n), 0) : 0) + 1,
5208
5542
  rootRef
@@ -5217,6 +5551,48 @@ var XrefParser = class {
5217
5551
  * Determine whether the data at the given offset starts with the
5218
5552
  * "xref" keyword (indicating a traditional xref table).
5219
5553
  */
5554
+ /**
5555
+ * Check if the bytes at `pos` match the given byte values.
5556
+ */
5557
+ matchesBytes(pos, ...bytes) {
5558
+ if (pos + bytes.length > this.data.length) return false;
5559
+ for (let i = 0; i < bytes.length; i++) if (this.data[pos + i] !== bytes[i]) return false;
5560
+ return true;
5561
+ }
5562
+ /**
5563
+ * Parse a standard xref entry directly from bytes, avoiding TextDecoder
5564
+ * and regex. Returns null if the bytes don't form a valid entry.
5565
+ *
5566
+ * Standard format: `OOOOOOOOOO GGGGG f/n` (18 significant bytes)
5567
+ */
5568
+ parseXrefEntryDirect(pos) {
5569
+ const d = this.data;
5570
+ if (pos + 18 > d.length) return null;
5571
+ let offset = 0;
5572
+ for (let k = 0; k < 10; k++) {
5573
+ const b = d[pos + k];
5574
+ if (b < 48 || b > 57) return null;
5575
+ offset = offset * 10 + (b - 48);
5576
+ }
5577
+ if (d[pos + 10] !== 32) return null;
5578
+ let gen = 0;
5579
+ for (let k = 0; k < 5; k++) {
5580
+ const b = d[pos + 11 + k];
5581
+ if (b < 48 || b > 57) return null;
5582
+ gen = gen * 10 + (b - 48);
5583
+ }
5584
+ if (d[pos + 16] !== 32) return null;
5585
+ const marker = d[pos + 17];
5586
+ if (marker !== 110 && marker !== 102) return null;
5587
+ let nextPos = pos + 18;
5588
+ while (nextPos < d.length && (d[nextPos] === 32 || d[nextPos] === 13 || d[nextPos] === 10)) nextPos++;
5589
+ return {
5590
+ offset,
5591
+ gen,
5592
+ type: marker === 110 ? "in-use" : "free",
5593
+ nextPos
5594
+ };
5595
+ }
5220
5596
  isTraditionalXref(offset) {
5221
5597
  if (offset + 4 > this.data.length) return false;
5222
5598
  return this.data[offset] === 120 && this.data[offset + 1] === 114 && this.data[offset + 2] === 101 && this.data[offset + 3] === 102;
@@ -6014,10 +6390,12 @@ function computeOwnerPasswordValue(ownerPassword, userPassword, revision, keyLen
6014
6390
  if (revision >= 3) for (let i = 0; i < 50; i++) hash = md5(hash.subarray(0, keyByteLength));
6015
6391
  const rc4Key = hash.subarray(0, keyByteLength);
6016
6392
  let encrypted = rc4(rc4Key, padPassword(userPassword));
6017
- if (revision >= 3) for (let i = 1; i <= 19; i++) {
6393
+ if (revision >= 3) {
6018
6394
  const modKey = new Uint8Array(rc4Key.length);
6019
- for (let j = 0; j < rc4Key.length; j++) modKey[j] = (rc4Key[j] ^ i) & 255;
6020
- encrypted = rc4(modKey, encrypted);
6395
+ for (let i = 1; i <= 19; i++) {
6396
+ for (let j = 0; j < rc4Key.length; j++) modKey[j] = (rc4Key[j] ^ i) & 255;
6397
+ encrypted = rc4(modKey, encrypted);
6398
+ }
6021
6399
  }
6022
6400
  return encrypted;
6023
6401
  }
@@ -6047,10 +6425,12 @@ function computeUserPasswordR2(fileKey) {
6047
6425
  */
6048
6426
  function computeUserPasswordR3R4(fileKey, fileId) {
6049
6427
  let encrypted = rc4(fileKey, md5(concat$1(PASSWORD_PADDING, fileId)));
6050
- for (let i = 1; i <= 19; i++) {
6428
+ {
6051
6429
  const modKey = new Uint8Array(fileKey.length);
6052
- for (let j = 0; j < fileKey.length; j++) modKey[j] = (fileKey[j] ^ i) & 255;
6053
- encrypted = rc4(modKey, encrypted);
6430
+ for (let i = 1; i <= 19; i++) {
6431
+ for (let j = 0; j < fileKey.length; j++) modKey[j] = (fileKey[j] ^ i) & 255;
6432
+ encrypted = rc4(modKey, encrypted);
6433
+ }
6054
6434
  }
6055
6435
  const result = new Uint8Array(32);
6056
6436
  result.set(encrypted.subarray(0, 16));
@@ -6116,9 +6496,17 @@ async function algorithm2B(password, salt, uKey) {
6116
6496
  let K = await sha256(uKey ? concat$1(password, salt, uKey) : concat$1(password, salt));
6117
6497
  let round = 0;
6118
6498
  while (true) {
6119
- const K1block = uKey ? concat$1(password, K, uKey) : concat$1(password, K);
6120
- const K1 = new Uint8Array(K1block.length * 64);
6121
- for (let i = 0; i < 64; i++) K1.set(K1block, i * K1block.length);
6499
+ const pLen = password.length;
6500
+ const kLen = K.length;
6501
+ const uLen = uKey ? uKey.length : 0;
6502
+ const blockLen = pLen + kLen + uLen;
6503
+ const K1 = new Uint8Array(blockLen * 64);
6504
+ for (let i = 0; i < 64; i++) {
6505
+ const base = i * blockLen;
6506
+ K1.set(password, base);
6507
+ K1.set(K, base + pLen);
6508
+ if (uKey) K1.set(uKey, base + pLen + kLen);
6509
+ }
6122
6510
  const E = await aesEncryptCBCNoPad(K.subarray(0, 16), K.subarray(16, 32), K1);
6123
6511
  let bigModVal = 0;
6124
6512
  for (let i = 0; i < 16; i++) bigModVal = (bigModVal * 256 + E[i]) % 3;
@@ -6915,7 +7303,13 @@ var PdfDocumentParser = class {
6915
7303
  * @param data The raw PDF file bytes as a Uint8Array.
6916
7304
  */
6917
7305
  constructor(data) {
6918
- if (data.length < 8) throw new Error("Invalid PDF: file is too short to contain a valid PDF header.");
7306
+ if (data.length < 8) throw new PdfParseError({
7307
+ message: "Invalid PDF: file is too short to contain a valid PDF header.",
7308
+ offset: 0,
7309
+ expected: "at least 8 bytes for a valid PDF header",
7310
+ actual: `${data.length} bytes`,
7311
+ data
7312
+ });
6919
7313
  this.data = data;
6920
7314
  }
6921
7315
  /**
@@ -6966,7 +7360,14 @@ var PdfDocumentParser = class {
6966
7360
  const { object } = this.objectParser.parseIndirectObjectAt(entry.offset);
6967
7361
  resolved = object;
6968
7362
  } catch (err) {
6969
- throw new Error(`Failed to parse indirect object ${objNum} ${entry.generationNumber} at offset ${entry.offset}`, { cause: err });
7363
+ throw new PdfParseError({
7364
+ message: `Failed to parse indirect object ${objNum} ${entry.generationNumber} at offset ${entry.offset}`,
7365
+ offset: entry.offset,
7366
+ expected: `valid indirect object ${objNum} ${entry.generationNumber}`,
7367
+ actual: "parse failure",
7368
+ data: this.data,
7369
+ cause: err instanceof Error ? err : void 0
7370
+ });
6970
7371
  }
6971
7372
  this.objectCache.set(objNum, resolved);
6972
7373
  return resolved;
@@ -6990,7 +7391,13 @@ var PdfDocumentParser = class {
6990
7391
  const encryptRef = this.trailer.encryptRef;
6991
7392
  this.encryptDictObjNum = encryptRef.objectNumber;
6992
7393
  const encryptObj = this.resolveRef(encryptRef);
6993
- if (encryptObj.kind !== "dict") throw new Error("Invalid PDF: /Encrypt entry is not a dictionary.");
7394
+ if (encryptObj.kind !== "dict") throw new PdfParseError({
7395
+ message: "Invalid PDF: /Encrypt entry is not a dictionary.",
7396
+ offset: 0,
7397
+ expected: "dictionary for /Encrypt entry",
7398
+ actual: `${encryptObj.kind}`,
7399
+ data: this.data
7400
+ });
6994
7401
  const encryptDict = encryptObj;
6995
7402
  const fileId = this.trailer.id?.[0] ?? new Uint8Array(0);
6996
7403
  const passwordsToTry = [];
@@ -7005,8 +7412,21 @@ var PdfDocumentParser = class {
7005
7412
  } catch (err) {
7006
7413
  lastError = err instanceof Error ? err : new Error(String(err));
7007
7414
  }
7008
- if (password !== void 0) throw new Error(`Failed to decrypt PDF: the provided password is incorrect. ${lastError?.message ?? ""}`);
7009
- else throw new Error("This PDF is encrypted and requires a password. Pass { password: \"...\" } in the options to decrypt it.");
7415
+ if (password !== void 0) throw new PdfParseError({
7416
+ message: `Failed to decrypt PDF: the provided password is incorrect. ${lastError?.message ?? ""}`,
7417
+ offset: 0,
7418
+ expected: "valid decryption password",
7419
+ actual: "incorrect password",
7420
+ data: this.data,
7421
+ cause: lastError
7422
+ });
7423
+ else throw new PdfParseError({
7424
+ message: "This PDF is encrypted and requires a password. Pass { password: \"...\" } in the options to decrypt it.",
7425
+ offset: 0,
7426
+ expected: "unencrypted PDF or password option",
7427
+ actual: "encrypted PDF without password",
7428
+ data: this.data
7429
+ });
7010
7430
  }
7011
7431
  /**
7012
7432
  * Decrypt all resolved objects in the object cache.
@@ -7102,7 +7522,12 @@ var PdfDocumentParser = class {
7102
7522
  * @throws If the page index is out of range.
7103
7523
  */
7104
7524
  getPageDict(pageIndex) {
7105
- if (pageIndex < 0 || pageIndex >= this.flattenedPages.length) throw new Error(`Page index ${pageIndex} is out of range. The document has ${this.flattenedPages.length} page(s).`);
7525
+ if (pageIndex < 0 || pageIndex >= this.flattenedPages.length) throw new PdfParseError({
7526
+ message: `Page index ${pageIndex} is out of range. The document has ${this.flattenedPages.length} page(s).`,
7527
+ offset: 0,
7528
+ expected: `page index in range [0, ${this.flattenedPages.length})`,
7529
+ actual: `${pageIndex}`
7530
+ });
7106
7531
  return this.flattenedPages[pageIndex].dict;
7107
7532
  }
7108
7533
  /**
@@ -7122,16 +7547,34 @@ var PdfDocumentParser = class {
7122
7547
  validateHeader() {
7123
7548
  const header = TEXT_DECODER.decode(this.data.subarray(0, Math.min(1024, this.data.length)));
7124
7549
  const pdfIdx = header.indexOf("%PDF-");
7125
- if (pdfIdx === -1 || pdfIdx > 1024) throw new Error("Invalid PDF: file does not start with \"%PDF-\" header. This may not be a PDF file.");
7550
+ if (pdfIdx === -1 || pdfIdx > 1024) throw new PdfParseError({
7551
+ message: "Invalid PDF: file does not start with \"%PDF-\" header. This may not be a PDF file.",
7552
+ offset: 0,
7553
+ expected: "\"%PDF-\" header near start of file",
7554
+ actual: "no \"%PDF-\" marker found",
7555
+ data: this.data
7556
+ });
7126
7557
  const versionMatch = header.substring(pdfIdx).match(/%PDF-(\d+\.\d+)/);
7127
- if (!versionMatch) throw new Error("Invalid PDF: could not parse version from header.");
7558
+ if (!versionMatch) throw new PdfParseError({
7559
+ message: "Invalid PDF: could not parse version from header.",
7560
+ offset: pdfIdx,
7561
+ expected: "\"%PDF-X.Y\" version string",
7562
+ actual: `"${header.substring(pdfIdx, pdfIdx + 10)}"`,
7563
+ data: this.data
7564
+ });
7128
7565
  this.pdfVersion = versionMatch[1];
7129
7566
  const majorMinor = this.pdfVersion.split(".");
7130
7567
  const major = parseInt(majorMinor[0], 10);
7131
7568
  const minor = parseInt(majorMinor[1], 10);
7132
7569
  if (major === 1 && minor >= 0 && minor <= 9) return;
7133
7570
  if (major === 2 && minor >= 0) return;
7134
- throw new Error(`Unsupported PDF version: ${this.pdfVersion}. Expected PDF 1.0-1.9 or 2.0+.`);
7571
+ throw new PdfParseError({
7572
+ message: `Unsupported PDF version: ${this.pdfVersion}. Expected PDF 1.0-1.9 or 2.0+.`,
7573
+ offset: 0,
7574
+ expected: "PDF version 1.0-1.9 or 2.0+",
7575
+ actual: `PDF version ${this.pdfVersion}`,
7576
+ data: this.data
7577
+ });
7135
7578
  }
7136
7579
  /**
7137
7580
  * Resolve the document catalog dictionary from the trailer's /Root
@@ -7139,12 +7582,24 @@ var PdfDocumentParser = class {
7139
7582
  */
7140
7583
  resolveCatalog() {
7141
7584
  const rootObj = this.resolveRef(this.trailer.rootRef);
7142
- if (rootObj.kind !== "dict") throw new Error(`Invalid PDF: /Root (catalog) at object ${this.trailer.rootRef.objectNumber} is not a dictionary (got ${rootObj.kind}).`);
7585
+ if (rootObj.kind !== "dict") throw new PdfParseError({
7586
+ message: `Invalid PDF: /Root (catalog) at object ${this.trailer.rootRef.objectNumber} is not a dictionary (got ${rootObj.kind}).`,
7587
+ offset: 0,
7588
+ expected: "dictionary for /Root (catalog)",
7589
+ actual: `${rootObj.kind}`,
7590
+ data: this.data
7591
+ });
7143
7592
  const catalog = rootObj;
7144
7593
  const typeObj = catalog.get("/Type");
7145
7594
  if (typeObj !== void 0 && typeObj.kind === "name") {
7146
7595
  const typeName = typeObj.value;
7147
- if (typeName !== "/Catalog") throw new Error(`Invalid PDF: /Root dictionary has /Type "${typeName}", expected "/Catalog".`);
7596
+ if (typeName !== "/Catalog") throw new PdfParseError({
7597
+ message: `Invalid PDF: /Root dictionary has /Type "${typeName}", expected "/Catalog".`,
7598
+ offset: 0,
7599
+ expected: "/Type /Catalog in /Root dictionary",
7600
+ actual: `/Type "${typeName}"`,
7601
+ data: this.data
7602
+ });
7148
7603
  }
7149
7604
  return catalog;
7150
7605
  }
@@ -7158,9 +7613,21 @@ var PdfDocumentParser = class {
7158
7613
  */
7159
7614
  resolvePageTree(catalog) {
7160
7615
  const pagesRef = catalog.get("/Pages");
7161
- if (pagesRef === void 0) throw new Error("Invalid PDF: catalog dictionary missing /Pages entry.");
7616
+ if (pagesRef === void 0) throw new PdfParseError({
7617
+ message: "Invalid PDF: catalog dictionary missing /Pages entry.",
7618
+ offset: 0,
7619
+ expected: "/Pages entry in catalog dictionary",
7620
+ actual: "no /Pages entry",
7621
+ data: this.data
7622
+ });
7162
7623
  const pagesObj = this.resolveObject(pagesRef);
7163
- if (pagesObj.kind !== "dict") throw new Error(`Invalid PDF: /Pages entry is not a dictionary (got ${pagesObj.kind}).`);
7624
+ if (pagesObj.kind !== "dict") throw new PdfParseError({
7625
+ message: `Invalid PDF: /Pages entry is not a dictionary (got ${pagesObj.kind}).`,
7626
+ offset: 0,
7627
+ expected: "dictionary for /Pages entry",
7628
+ actual: `${pagesObj.kind}`,
7629
+ data: this.data
7630
+ });
7164
7631
  const pages = [];
7165
7632
  this.traversePageTree(pagesObj, {}, pages, /* @__PURE__ */ new Set());
7166
7633
  return pages;
@@ -7197,7 +7664,13 @@ var PdfDocumentParser = class {
7197
7664
  }
7198
7665
  if (typeName === "/Page") {
7199
7666
  const mediaBox = currentInherited.mediaBox;
7200
- if (mediaBox === void 0) throw new Error("Invalid PDF: /Page node has no /MediaBox (not even inherited).");
7667
+ if (mediaBox === void 0) throw new PdfParseError({
7668
+ message: "Invalid PDF: /Page node has no /MediaBox (not even inherited).",
7669
+ offset: 0,
7670
+ expected: "/MediaBox on page node or inherited from parent",
7671
+ actual: "no /MediaBox found",
7672
+ data: this.data
7673
+ });
7201
7674
  result.push({
7202
7675
  dict: node,
7203
7676
  mediaBox,
@@ -7209,7 +7682,13 @@ var PdfDocumentParser = class {
7209
7682
  const kidsObj = node.get("/Kids");
7210
7683
  if (kidsObj === void 0) return;
7211
7684
  const kids = this.resolveObject(kidsObj);
7212
- if (kids.kind !== "array") throw new Error(`Invalid PDF: /Pages /Kids is not an array (got ${kids.kind}).`);
7685
+ if (kids.kind !== "array") throw new PdfParseError({
7686
+ message: `Invalid PDF: /Pages /Kids is not an array (got ${kids.kind}).`,
7687
+ offset: 0,
7688
+ expected: "array for /Pages /Kids",
7689
+ actual: `${kids.kind}`,
7690
+ data: this.data
7691
+ });
7213
7692
  const kidsArr = kids;
7214
7693
  for (let i = 0; i < kidsArr.length; i++) {
7215
7694
  const kidRef = kidsArr.items[i];
@@ -7245,22 +7724,53 @@ var PdfDocumentParser = class {
7245
7724
  return PdfNull.instance;
7246
7725
  }
7247
7726
  const containerEntry = this.xrefEntries.get(containerNum);
7248
- if (containerEntry === void 0 || containerEntry.type !== "in-use") throw new Error(`Invalid PDF: object stream ${containerNum} referenced by compressed object ${entry.objectNumber} not found in xref table.`);
7727
+ if (containerEntry === void 0 || containerEntry.type !== "in-use") throw new PdfParseError({
7728
+ message: `Invalid PDF: object stream ${containerNum} referenced by compressed object ${entry.objectNumber} not found in xref table.`,
7729
+ offset: 0,
7730
+ expected: `in-use xref entry for object stream ${containerNum}`,
7731
+ actual: containerEntry ? `${containerEntry.type} entry` : "no entry",
7732
+ data: this.data
7733
+ });
7249
7734
  let containerObj;
7250
7735
  try {
7251
7736
  const { object } = this.objectParser.parseIndirectObjectAt(containerEntry.offset);
7252
7737
  containerObj = object;
7253
7738
  } catch (err) {
7254
- throw new Error(`Failed to parse object stream ${containerNum} at offset ${containerEntry.offset}`, { cause: err });
7739
+ throw new PdfParseError({
7740
+ message: `Failed to parse object stream ${containerNum} at offset ${containerEntry.offset}`,
7741
+ offset: containerEntry.offset,
7742
+ expected: `valid object stream ${containerNum}`,
7743
+ actual: "parse failure",
7744
+ data: this.data,
7745
+ cause: err instanceof Error ? err : void 0
7746
+ });
7255
7747
  }
7256
- if (containerObj.kind !== "stream") throw new Error(`Invalid PDF: object ${containerNum} expected to be an object stream but is ${containerObj.kind}.`);
7748
+ if (containerObj.kind !== "stream") throw new PdfParseError({
7749
+ message: `Invalid PDF: object ${containerNum} expected to be an object stream but is ${containerObj.kind}.`,
7750
+ offset: containerEntry.offset,
7751
+ expected: "stream object for object stream",
7752
+ actual: `${containerObj.kind}`,
7753
+ data: this.data
7754
+ });
7257
7755
  const containerStream = containerObj;
7258
7756
  const containerDict = containerStream.dict;
7259
7757
  const typeObj = containerDict.get("/Type");
7260
- if (typeObj === void 0 || typeObj.kind !== "name" || typeObj.value !== "/ObjStm") throw new Error(`Invalid PDF: object ${containerNum} is not an object stream (/Type /ObjStm).`);
7758
+ if (typeObj === void 0 || typeObj.kind !== "name" || typeObj.value !== "/ObjStm") throw new PdfParseError({
7759
+ message: `Invalid PDF: object ${containerNum} is not an object stream (/Type /ObjStm).`,
7760
+ offset: containerEntry.offset,
7761
+ expected: "/Type /ObjStm in object stream dictionary",
7762
+ actual: typeObj ? `${typeObj.kind}` : "no /Type entry",
7763
+ data: this.data
7764
+ });
7261
7765
  const n = numVal$1(containerDict.get("/N"));
7262
7766
  const first = numVal$1(containerDict.get("/First"));
7263
- if (n === void 0 || first === void 0) throw new Error(`Invalid PDF: object stream ${containerNum} missing /N or /First entries.`);
7767
+ if (n === void 0 || first === void 0) throw new PdfParseError({
7768
+ message: `Invalid PDF: object stream ${containerNum} missing /N or /First entries.`,
7769
+ offset: containerEntry.offset,
7770
+ expected: "/N and /First entries in object stream",
7771
+ actual: `${n === void 0 ? "no /N" : "/N present"}, ${first === void 0 ? "no /First" : "/First present"}`,
7772
+ data: this.data
7773
+ });
7264
7774
  const decompressedData = this.decompressStreamSync(containerStream);
7265
7775
  const headerTokens = TEXT_DECODER.decode(decompressedData.subarray(0, first)).trim().split(/\s+/);
7266
7776
  const objEntries = [];
@@ -7657,7 +8167,7 @@ function undoPngPredictorSync(data, columns) {
7657
8167
  * string.
7658
8168
  *
7659
8169
  * This is the primary entry point for parsing existing PDFs. It creates
7660
- * a {@link PdfDocumentParser}, runs the full parse pipeline, and returns
8170
+ * a `PdfDocumentParser`, runs the full parse pipeline, and returns
7661
8171
  * a populated {@link PdfDocument}.
7662
8172
  *
7663
8173
  * @param data The PDF data as a `Uint8Array`, `ArrayBuffer`, or a
@@ -8148,7 +8658,17 @@ const NS_PDFAID = "http://www.aiim.org/pdfa/ns/id/";
8148
8658
  * @internal
8149
8659
  */
8150
8660
  function escapeXml(str) {
8151
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
8661
+ const parts = [];
8662
+ for (let i = 0; i < str.length; i++) {
8663
+ const c = str.charCodeAt(i);
8664
+ if (c === 38) parts.push("&amp;");
8665
+ else if (c === 60) parts.push("&lt;");
8666
+ else if (c === 62) parts.push("&gt;");
8667
+ else if (c === 34) parts.push("&quot;");
8668
+ else if (c === 39) parts.push("&apos;");
8669
+ else parts.push(str[i]);
8670
+ }
8671
+ return parts.join("");
8152
8672
  }
8153
8673
  /**
8154
8674
  * Format a Date as an ISO 8601 string for XMP.
@@ -9451,9 +9971,10 @@ function remapRef$1(sourceRef, context) {
9451
9971
  context.refMap.set(sourceRef.objectNumber, placeholderRef);
9452
9972
  return placeholderRef;
9453
9973
  }
9974
+ let streamHash;
9454
9975
  if (sourceObj.kind === "stream") {
9455
- const hash = hashBytes(sourceObj.data);
9456
- const dedup = context.hashMap.get(hash);
9976
+ streamHash = hashBytes(sourceObj.data);
9977
+ const dedup = context.hashMap.get(streamHash);
9457
9978
  if (dedup) {
9458
9979
  context.refMap.set(sourceRef.objectNumber, dedup);
9459
9980
  return dedup;
@@ -9463,10 +9984,7 @@ function remapRef$1(sourceRef, context) {
9463
9984
  context.refMap.set(sourceRef.objectNumber, targetRef);
9464
9985
  const clonedObj = deepClone$1(sourceObj, context);
9465
9986
  context.targetRegistry.assign(targetRef, clonedObj);
9466
- if (sourceObj.kind === "stream") {
9467
- const hash = hashBytes(sourceObj.data);
9468
- context.hashMap.set(hash, targetRef);
9469
- }
9987
+ if (streamHash !== void 0) context.hashMap.set(streamHash, targetRef);
9470
9988
  return targetRef;
9471
9989
  }
9472
9990
  /**
@@ -14045,7 +14563,6 @@ function read2DMode(reader) {
14045
14563
  if (bit === 1) {
14046
14564
  bit = reader.readBit();
14047
14565
  if (bit < 0) return Mode2D.EOL;
14048
- if (bit === 1) return Mode2D.HORIZONTAL;
14049
14566
  if (bit === 0) return Mode2D.VERTICAL_MINUS_1;
14050
14567
  return Mode2D.VERTICAL_PLUS_1;
14051
14568
  }
@@ -14211,6 +14728,9 @@ function packBits(pixels, columns, blackIs1) {
14211
14728
  /**
14212
14729
  * Decode JBIG2Decode stream data.
14213
14730
  *
14731
+ * Uses the pure-JS decoder (synchronous). For optional WASM
14732
+ * acceleration, use {@link decodeJBIG2Async}.
14733
+ *
14214
14734
  * @param data - The JBIG2-encoded content stream bytes.
14215
14735
  * @param parms - Optional `/DecodeParms` dictionary. May contain a
14216
14736
  * `/JBIG2Globals` key with a PdfDict/stream holding
@@ -17173,9 +17693,28 @@ function hexValue(ch) {
17173
17693
  * `~>` marks end-of-data.
17174
17694
  */
17175
17695
  function decodeASCII85(data) {
17176
- const result = [];
17177
- const group = [];
17696
+ let out = new Uint8Array(Math.max(data.length * 4 / 5 | 0, 256));
17697
+ let outPos = 0;
17698
+ const group = new Uint8Array(5);
17699
+ let groupLen = 0;
17178
17700
  let i = 0;
17701
+ function ensureOut(needed) {
17702
+ if (outPos + needed > out.length) {
17703
+ const newBuf = new Uint8Array(Math.max(out.length * 2, outPos + needed));
17704
+ newBuf.set(out.subarray(0, outPos));
17705
+ out = newBuf;
17706
+ }
17707
+ }
17708
+ function decodeGroup(count) {
17709
+ for (let k = count; k < 5; k++) group[k] = 84;
17710
+ const val = group[0] * 85 * 85 * 85 * 85 + group[1] * 85 * 85 * 85 + group[2] * 85 * 85 + group[3] * 85 + group[4];
17711
+ const numBytes = count === 5 ? 4 : count - 1;
17712
+ ensureOut(numBytes);
17713
+ if (numBytes >= 1) out[outPos++] = val >>> 24 & 255;
17714
+ if (numBytes >= 2) out[outPos++] = val >>> 16 & 255;
17715
+ if (numBytes >= 3) out[outPos++] = val >>> 8 & 255;
17716
+ if (numBytes >= 4) out[outPos++] = val & 255;
17717
+ }
17179
17718
  while (i < data.length) {
17180
17719
  const ch = data[i];
17181
17720
  if (ch === 126) break;
@@ -17184,8 +17723,12 @@ function decodeASCII85(data) {
17184
17723
  continue;
17185
17724
  }
17186
17725
  if (ch === 122) {
17187
- if (group.length > 0) throw new Error("ASCII85Decode: \"z\" inside a group");
17188
- result.push(0, 0, 0, 0);
17726
+ if (groupLen > 0) throw new Error("ASCII85Decode: \"z\" inside a group");
17727
+ ensureOut(4);
17728
+ out[outPos++] = 0;
17729
+ out[outPos++] = 0;
17730
+ out[outPos++] = 0;
17731
+ out[outPos++] = 0;
17189
17732
  i++;
17190
17733
  continue;
17191
17734
  }
@@ -17193,24 +17736,15 @@ function decodeASCII85(data) {
17193
17736
  i++;
17194
17737
  continue;
17195
17738
  }
17196
- group.push(ch - 33);
17197
- if (group.length === 5) {
17198
- const val = group[0] * 85 * 85 * 85 * 85 + group[1] * 85 * 85 * 85 + group[2] * 85 * 85 + group[3] * 85 + group[4];
17199
- result.push(val >>> 24 & 255, val >>> 16 & 255, val >>> 8 & 255, val & 255);
17200
- group.length = 0;
17739
+ group[groupLen++] = ch - 33;
17740
+ if (groupLen === 5) {
17741
+ decodeGroup(5);
17742
+ groupLen = 0;
17201
17743
  }
17202
17744
  i++;
17203
17745
  }
17204
- if (group.length >= 2) {
17205
- const origLen = group.length;
17206
- while (group.length < 5) group.push(84);
17207
- const val = group[0] * 85 * 85 * 85 * 85 + group[1] * 85 * 85 * 85 + group[2] * 85 * 85 + group[3] * 85 + group[4];
17208
- const numBytes = origLen - 1;
17209
- if (numBytes >= 1) result.push(val >>> 24 & 255);
17210
- if (numBytes >= 2) result.push(val >>> 16 & 255);
17211
- if (numBytes >= 3) result.push(val >>> 8 & 255);
17212
- }
17213
- return new Uint8Array(result);
17746
+ if (groupLen >= 2) decodeGroup(groupLen);
17747
+ return out.subarray(0, outPos);
17214
17748
  }
17215
17749
  /**
17216
17750
  * Decode an LZWDecode stream.
@@ -17230,6 +17764,10 @@ function decodeLZW(data, parms) {
17230
17764
  }
17231
17765
  /**
17232
17766
  * Core LZW decompression.
17767
+ *
17768
+ * Uses a flat pooled buffer for the code table instead of per-entry
17769
+ * Uint8Array allocations, and a pre-allocated output buffer with
17770
+ * manual growth instead of `number[]` + push.
17233
17771
  */
17234
17772
  function lzwDecompress(data, earlyChange) {
17235
17773
  const CLEAR_TABLE = 256;
@@ -17254,71 +17792,88 @@ function lzwDecompress(data, earlyChange) {
17254
17792
  }
17255
17793
  return result;
17256
17794
  }
17257
- let table = [];
17795
+ let tableBuf = new Uint8Array(65536);
17796
+ const tableOff = new Int32Array(4096);
17797
+ const tableLen = new Int32Array(4096);
17798
+ let tableBufUsed = 256;
17258
17799
  let codeSize = 9;
17259
17800
  let nextCode = 258;
17801
+ for (let i = 0; i < 256; i++) {
17802
+ tableBuf[i] = i;
17803
+ tableOff[i] = i;
17804
+ tableLen[i] = 1;
17805
+ }
17260
17806
  function resetTable() {
17261
- table = [];
17262
- for (let i = 0; i < 256; i++) table[i] = new Uint8Array([i]);
17263
- table[256] = new Uint8Array(0);
17264
- table[257] = new Uint8Array(0);
17807
+ tableBufUsed = 256;
17265
17808
  nextCode = 258;
17266
17809
  codeSize = 9;
17267
17810
  }
17268
- resetTable();
17269
- const output = [];
17270
- let prevEntry = null;
17811
+ let out = new Uint8Array(Math.max(data.length * 3, 4096));
17812
+ let outPos = 0;
17813
+ function ensureOut(needed) {
17814
+ if (outPos + needed > out.length) {
17815
+ const newBuf = new Uint8Array(Math.max(out.length * 2, outPos + needed));
17816
+ newBuf.set(out.subarray(0, outPos));
17817
+ out = newBuf;
17818
+ }
17819
+ }
17820
+ function ensureTable(needed) {
17821
+ if (tableBufUsed + needed > tableBuf.length) {
17822
+ const newBuf = new Uint8Array(Math.max(tableBuf.length * 2, tableBufUsed + needed));
17823
+ newBuf.set(tableBuf.subarray(0, tableBufUsed));
17824
+ tableBuf = newBuf;
17825
+ }
17826
+ }
17827
+ function writeEntry(code) {
17828
+ const off = tableOff[code];
17829
+ const len = tableLen[code];
17830
+ ensureOut(len);
17831
+ out.set(tableBuf.subarray(off, off + len), outPos);
17832
+ outPos += len;
17833
+ }
17834
+ function addEntry(prevCode, firstByte) {
17835
+ const prevOff = tableOff[prevCode];
17836
+ const prevLen = tableLen[prevCode];
17837
+ const newLen = prevLen + 1;
17838
+ ensureTable(newLen);
17839
+ tableBuf.set(tableBuf.subarray(prevOff, prevOff + prevLen), tableBufUsed);
17840
+ tableBuf[tableBufUsed + prevLen] = firstByte;
17841
+ tableOff[nextCode] = tableBufUsed;
17842
+ tableLen[nextCode] = newLen;
17843
+ tableBufUsed += newLen;
17844
+ nextCode++;
17845
+ }
17271
17846
  let code = readBits(codeSize);
17272
17847
  if (code === CLEAR_TABLE) {
17273
17848
  resetTable();
17274
17849
  code = readBits(codeSize);
17275
17850
  }
17276
- if (code === EOD) return new Uint8Array(output);
17277
- let entry = table[code];
17278
- if (entry) {
17279
- for (const b of entry) output.push(b);
17280
- prevEntry = entry;
17281
- }
17851
+ if (code === EOD) return new Uint8Array(0);
17852
+ writeEntry(code);
17853
+ let prevCode = code;
17282
17854
  while (true) {
17283
17855
  code = readBits(codeSize);
17284
17856
  if (code === EOD) break;
17285
17857
  if (code === CLEAR_TABLE) {
17286
17858
  resetTable();
17287
- prevEntry = null;
17288
17859
  code = readBits(codeSize);
17289
17860
  if (code === EOD) break;
17290
- entry = table[code];
17291
- if (entry) {
17292
- for (const b of entry) output.push(b);
17293
- prevEntry = entry;
17294
- }
17861
+ writeEntry(code);
17862
+ prevCode = code;
17295
17863
  continue;
17296
17864
  }
17297
- if (code < nextCode && table[code]) {
17298
- entry = table[code];
17299
- for (const b of entry) output.push(b);
17300
- if (prevEntry) {
17301
- const newEntry = new Uint8Array(prevEntry.length + 1);
17302
- newEntry.set(prevEntry);
17303
- newEntry[prevEntry.length] = entry[0];
17304
- table[nextCode] = newEntry;
17305
- nextCode++;
17306
- }
17865
+ if (code < nextCode) {
17866
+ writeEntry(code);
17867
+ addEntry(prevCode, tableBuf[tableOff[code]]);
17307
17868
  } else {
17308
- if (!prevEntry) throw new Error("LZWDecode: invalid code sequence");
17309
- const newEntry = new Uint8Array(prevEntry.length + 1);
17310
- newEntry.set(prevEntry);
17311
- newEntry[prevEntry.length] = prevEntry[0];
17312
- for (const b of newEntry) output.push(b);
17313
- table[nextCode] = newEntry;
17314
- nextCode++;
17315
- entry = newEntry;
17316
- }
17317
- prevEntry = entry;
17869
+ addEntry(prevCode, tableBuf[tableOff[prevCode]]);
17870
+ writeEntry(nextCode - 1);
17871
+ }
17872
+ prevCode = code;
17318
17873
  const threshold = (1 << codeSize) - earlyChange;
17319
17874
  if (nextCode >= threshold && codeSize < 12) codeSize++;
17320
17875
  }
17321
- return new Uint8Array(output);
17876
+ return out.subarray(0, outPos);
17322
17877
  }
17323
17878
  /**
17324
17879
  * Decode a RunLengthDecode stream.
@@ -17450,7 +18005,6 @@ function embedPageAsFormXObject(page, sourceRegistry, targetRegistry, xObjectNam
17450
18005
  const pageWidth = page.width;
17451
18006
  const pageHeight = page.height;
17452
18007
  const contentChunks = [];
17453
- new TextDecoder();
17454
18008
  const originalRefs = page.getOriginalContentRefs();
17455
18009
  for (const ref of originalRefs) {
17456
18010
  const obj = sourceRegistry.resolve(ref);
@@ -17535,6 +18089,93 @@ function embedPageAsFormXObject(page, sourceRegistry, targetRegistry, xObjectNam
17535
18089
  };
17536
18090
  }
17537
18091
 
18092
+ //#endregion
18093
+ //#region src/core/pdfDocumentEmbed.ts
18094
+ /**
18095
+ * @module core/pdfDocumentEmbed
18096
+ *
18097
+ * Pure helper functions for font CMap generation and image format
18098
+ * validation/parsing. Extracted from {@link pdfDocument} to keep the
18099
+ * PdfDocument class focused on high-level document management.
18100
+ */
18101
+ /**
18102
+ * Build a /ToUnicode CMap from a font's cmap table.
18103
+ * Maps glyph IDs (used as CIDs with Identity-H) to Unicode codepoints.
18104
+ *
18105
+ * @param cmapTable Mapping from Unicode codepoint to glyph ID.
18106
+ * @returns A CMap string suitable for a PDF /ToUnicode stream.
18107
+ */
18108
+ function buildToUnicodeCmap(cmapTable) {
18109
+ const gidToUnicode = /* @__PURE__ */ new Map();
18110
+ for (const [codepoint, gid] of cmapTable) if (!gidToUnicode.has(gid)) gidToUnicode.set(gid, codepoint);
18111
+ const entries = gidToUnicode.entries().toArray().sort((a, b) => a[0] - b[0]);
18112
+ const lines = [];
18113
+ lines.push("/CIDInit /ProcSet findresource begin");
18114
+ lines.push("12 dict begin");
18115
+ lines.push("begincmap");
18116
+ lines.push("/CIDSystemInfo");
18117
+ lines.push("<< /Registry (Adobe)");
18118
+ lines.push("/Ordering (UCS)");
18119
+ lines.push("/Supplement 0");
18120
+ lines.push(">> def");
18121
+ lines.push("/CMapName /Adobe-Identity-UCS def");
18122
+ lines.push("/CMapType 2 def");
18123
+ lines.push("1 begincodespacerange");
18124
+ lines.push("<0000> <FFFF>");
18125
+ lines.push("endcodespacerange");
18126
+ const CHUNK_SIZE = 100;
18127
+ for (let i = 0; i < entries.length; i += CHUNK_SIZE) {
18128
+ const chunk = entries.slice(i, i + CHUNK_SIZE);
18129
+ lines.push(`${chunk.length} beginbfchar`);
18130
+ for (const [gid, codepoint] of chunk) {
18131
+ const gidHex = gid.toString(16).padStart(4, "0").toUpperCase();
18132
+ const uniHex = codepoint.toString(16).padStart(4, "0").toUpperCase();
18133
+ lines.push(`<${gidHex}> <${uniHex}>`);
18134
+ }
18135
+ lines.push("endbfchar");
18136
+ }
18137
+ lines.push("endcmap");
18138
+ lines.push("CMapName currentdict /CMap defineresource pop");
18139
+ lines.push("end");
18140
+ lines.push("end");
18141
+ return lines.join("\n");
18142
+ }
18143
+ /**
18144
+ * Validate a JPEG file signature (SOI marker).
18145
+ *
18146
+ * @param data The raw file bytes.
18147
+ * @throws If the data is too short or the SOI marker is invalid.
18148
+ */
18149
+ function validateJpegSignature(data) {
18150
+ if (data.length < 2 || data[0] !== 255 || data[1] !== 216) throw new Error("Invalid JPEG: bad SOI marker");
18151
+ }
18152
+ /**
18153
+ * Parse width, height, and component count from a JPEG's SOF marker.
18154
+ *
18155
+ * @param data The raw JPEG file bytes.
18156
+ * @returns Width, height, and number of color components.
18157
+ */
18158
+ function parseJpegDimensions(data) {
18159
+ validateJpegSignature(data);
18160
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
18161
+ let offset = 2;
18162
+ while (offset < data.length - 1) {
18163
+ if (data[offset] !== 255) throw new Error("Invalid JPEG: expected marker");
18164
+ const marker = data[offset + 1];
18165
+ if (marker >= 192 && marker <= 195 || marker >= 197 && marker <= 199 || marker >= 201 && marker <= 203 || marker >= 205 && marker <= 207) {
18166
+ const height = view.getUint16(offset + 5, false);
18167
+ return {
18168
+ width: view.getUint16(offset + 7, false),
18169
+ height,
18170
+ components: data[offset + 9]
18171
+ };
18172
+ }
18173
+ const segmentLength = view.getUint16(offset + 2, false);
18174
+ offset += 2 + segmentLength;
18175
+ }
18176
+ throw new Error("Invalid JPEG: SOF marker not found");
18177
+ }
18178
+
17538
18179
  //#endregion
17539
18180
  //#region src/core/pdfDocument.ts
17540
18181
  /**
@@ -17881,7 +18522,7 @@ var PdfDocument = class PdfDocument {
17881
18522
  async embedTrueTypeFont(fontData, options) {
17882
18523
  const embeddedFont = await embedFont(fontData);
17883
18524
  const metrics = embeddedFont.metrics;
17884
- const psName = options?.customName || metrics.postScriptName || metrics.familyName || "CustomFont";
18525
+ const psName = options?.customName ?? metrics.postScriptName ?? metrics.familyName ?? "CustomFont";
17885
18526
  const existing = this.embeddedFonts.get(`__ttf__${psName}`);
17886
18527
  if (existing) return existing;
17887
18528
  this.fontCounter++;
@@ -17938,7 +18579,7 @@ var PdfDocument = class PdfDocument {
17938
18579
  cidFontDict.set("/DW", PdfNumber.of(Math.round(metrics.defaultWidth * scale)));
17939
18580
  cidFontDict.set("/CIDToGIDMap", PdfName.of("Identity"));
17940
18581
  const cidFontRef = this.registry.register(cidFontDict);
17941
- const toUnicodeCmapStr = this.buildToUnicodeCmap(metrics.cmapTable);
18582
+ const toUnicodeCmapStr = buildToUnicodeCmap(metrics.cmapTable);
17942
18583
  const toUnicodeStream = PdfStream.fromString(toUnicodeCmapStr);
17943
18584
  const toUnicodeRef = this.registry.register(toUnicodeStream);
17944
18585
  const type0Dict = new PdfDict();
@@ -17996,7 +18637,7 @@ var PdfDocument = class PdfDocument {
17996
18637
  async embedCffFont(fontData, options) {
17997
18638
  const embeddedFont = await embedFont(fontData);
17998
18639
  const metrics = embeddedFont.metrics;
17999
- const psName = options?.customName || metrics.postScriptName || metrics.familyName || "CFFFont";
18640
+ const psName = options?.customName ?? metrics.postScriptName ?? metrics.familyName ?? "CFFFont";
18000
18641
  const existing = this.embeddedFonts.get(`__cff__${psName}`);
18001
18642
  if (existing) return existing;
18002
18643
  this.fontCounter++;
@@ -18055,7 +18696,7 @@ var PdfDocument = class PdfDocument {
18055
18696
  cidFontDict.set("/W", wArray);
18056
18697
  cidFontDict.set("/DW", PdfNumber.of(Math.round(metrics.defaultWidth * scale)));
18057
18698
  const cidFontRef = this.registry.register(cidFontDict);
18058
- const toUnicodeCmapStr = this.buildToUnicodeCmap(metrics.cmapTable);
18699
+ const toUnicodeCmapStr = buildToUnicodeCmap(metrics.cmapTable);
18059
18700
  const toUnicodeStream = PdfStream.fromString(toUnicodeCmapStr);
18060
18701
  const toUnicodeRef = this.registry.register(toUnicodeStream);
18061
18702
  const type0Dict = new PdfDict();
@@ -18101,46 +18742,6 @@ var PdfDocument = class PdfDocument {
18101
18742
  return fontRef;
18102
18743
  }
18103
18744
  /**
18104
- * Build a /ToUnicode CMap from the font's cmap table.
18105
- * Maps glyph IDs (used as CIDs with Identity-H) to Unicode codepoints.
18106
- * @internal
18107
- */
18108
- buildToUnicodeCmap(cmapTable) {
18109
- const gidToUnicode = /* @__PURE__ */ new Map();
18110
- for (const [codepoint, gid] of cmapTable) if (!gidToUnicode.has(gid)) gidToUnicode.set(gid, codepoint);
18111
- const entries = gidToUnicode.entries().toArray().sort((a, b) => a[0] - b[0]);
18112
- const lines = [];
18113
- lines.push("/CIDInit /ProcSet findresource begin");
18114
- lines.push("12 dict begin");
18115
- lines.push("begincmap");
18116
- lines.push("/CIDSystemInfo");
18117
- lines.push("<< /Registry (Adobe)");
18118
- lines.push("/Ordering (UCS)");
18119
- lines.push("/Supplement 0");
18120
- lines.push(">> def");
18121
- lines.push("/CMapName /Adobe-Identity-UCS def");
18122
- lines.push("/CMapType 2 def");
18123
- lines.push("1 begincodespacerange");
18124
- lines.push("<0000> <FFFF>");
18125
- lines.push("endcodespacerange");
18126
- const CHUNK_SIZE = 100;
18127
- for (let i = 0; i < entries.length; i += CHUNK_SIZE) {
18128
- const chunk = entries.slice(i, i + CHUNK_SIZE);
18129
- lines.push(`${chunk.length} beginbfchar`);
18130
- for (const [gid, codepoint] of chunk) {
18131
- const gidHex = gid.toString(16).padStart(4, "0").toUpperCase();
18132
- const uniHex = codepoint.toString(16).padStart(4, "0").toUpperCase();
18133
- lines.push(`<${gidHex}> <${uniHex}>`);
18134
- }
18135
- lines.push("endbfchar");
18136
- }
18137
- lines.push("endcmap");
18138
- lines.push("CMapName currentdict /CMap defineresource pop");
18139
- lines.push("end");
18140
- lines.push("end");
18141
- return lines.join("\n");
18142
- }
18143
- /**
18144
18745
  * Embed a PNG image.
18145
18746
  *
18146
18747
  * Fully decodes the PNG (including filter reconstruction and alpha
@@ -18326,7 +18927,7 @@ var PdfDocument = class PdfDocument {
18326
18927
  * @param pages Array of PdfPage instances to embed.
18327
18928
  * @returns Array of {@link EmbeddedPdfPage} handles, one per input page.
18328
18929
  */
18329
- async embedPages(pages) {
18930
+ embedPages(pages) {
18330
18931
  return pages.map((page) => this.embedPage(page));
18331
18932
  }
18332
18933
  /** Set the document title. */
@@ -18809,6 +19410,79 @@ var PdfDocument = class PdfDocument {
18809
19410
  addWatermark(this, options);
18810
19411
  }
18811
19412
  /**
19413
+ * Create a soft mask Form XObject that can be used with
19414
+ * {@link PdfPage.applySoftMask}.
19415
+ *
19416
+ * The builder callback receives a {@link SoftMaskBuilder} with methods
19417
+ * for generating grayscale content where white (`1`) represents fully
19418
+ * opaque regions and black (`0`) represents fully transparent regions.
19419
+ *
19420
+ * The returned {@link SoftMaskRef} is passed to
19421
+ * {@link PdfPage.applySoftMask} to activate the mask for subsequent
19422
+ * drawing operations on that page.
19423
+ *
19424
+ * @param width Width of the mask in points.
19425
+ * @param height Height of the mask in points.
19426
+ * @param builder Callback that draws the mask content.
19427
+ * @returns A reference to the soft mask Form XObject.
19428
+ *
19429
+ * @example
19430
+ * ```ts
19431
+ * const mask = doc.createSoftMask(200, 200, (b) => {
19432
+ * // White background = fully opaque
19433
+ * b.drawRectangle(0, 0, 200, 200, 1);
19434
+ * // Black circle = fully transparent hole
19435
+ * b.drawCircle(100, 100, 80, 0);
19436
+ * });
19437
+ * page.applySoftMask(mask);
19438
+ * page.drawRectangle({ x: 50, y: 50, width: 200, height: 200, color: rgb(1, 0, 0) });
19439
+ * page.clearSoftMask();
19440
+ * ```
19441
+ */
19442
+ createSoftMask(width, height, builder) {
19443
+ const maskOps = [];
19444
+ const kappa = .5522847498;
19445
+ builder({
19446
+ drawRectangle(x, y, w, h, gray) {
19447
+ maskOps.push(`${gray} g`);
19448
+ maskOps.push(`${x} ${y} ${w} ${h} re`);
19449
+ maskOps.push("f");
19450
+ },
19451
+ drawCircle(cx, cy, r, gray) {
19452
+ maskOps.push(`${gray} g`);
19453
+ const ox = r * kappa;
19454
+ const oy = r * kappa;
19455
+ maskOps.push(`${cx - r} ${cy} m`);
19456
+ maskOps.push(`${cx - r} ${cy + oy} ${cx - ox} ${cy + r} ${cx} ${cy + r} c`);
19457
+ maskOps.push(`${cx + ox} ${cy + r} ${cx + r} ${cy + oy} ${cx + r} ${cy} c`);
19458
+ maskOps.push(`${cx + r} ${cy - oy} ${cx + ox} ${cy - r} ${cx} ${cy - r} c`);
19459
+ maskOps.push(`${cx - ox} ${cy - r} ${cx - r} ${cy - oy} ${cx - r} ${cy} c`);
19460
+ maskOps.push("f");
19461
+ },
19462
+ pushRawOperators(ops) {
19463
+ maskOps.push(ops);
19464
+ }
19465
+ });
19466
+ const groupDict = new PdfDict();
19467
+ groupDict.set("/S", PdfName.of("Transparency"));
19468
+ groupDict.set("/CS", PdfName.of("DeviceGray"));
19469
+ const formDict = new PdfDict();
19470
+ formDict.set("/Type", PdfName.of("XObject"));
19471
+ formDict.set("/Subtype", PdfName.of("Form"));
19472
+ formDict.set("/BBox", PdfArray.fromNumbers([
19473
+ 0,
19474
+ 0,
19475
+ width,
19476
+ height
19477
+ ]));
19478
+ formDict.set("/Group", groupDict);
19479
+ const stream = PdfStream.fromString(maskOps.join("\n"), formDict);
19480
+ return {
19481
+ _tag: "softMask",
19482
+ ref: this.registry.register(stream)
19483
+ };
19484
+ }
19485
+ /**
18812
19486
  * Apply all pending redactions across all pages.
18813
19487
  *
18814
19488
  * Redaction marks are added to individual pages using
@@ -19043,30 +19717,6 @@ var PdfDocument = class PdfDocument {
19043
19717
  function createPdf() {
19044
19718
  return new PdfDocument();
19045
19719
  }
19046
- /**
19047
- * Parse width, height, and component count from a JPEG's SOF marker.
19048
- * @internal
19049
- */
19050
- function parseJpegDimensions(data) {
19051
- if (data.length < 2 || data[0] !== 255 || data[1] !== 216) throw new Error("Invalid JPEG: bad SOI marker");
19052
- const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
19053
- let offset = 2;
19054
- while (offset < data.length - 1) {
19055
- if (data[offset] !== 255) throw new Error("Invalid JPEG: expected marker");
19056
- const marker = data[offset + 1];
19057
- if (marker >= 192 && marker <= 195 || marker >= 197 && marker <= 199 || marker >= 201 && marker <= 203 || marker >= 205 && marker <= 207) {
19058
- const height = view.getUint16(offset + 5, false);
19059
- return {
19060
- width: view.getUint16(offset + 7, false),
19061
- height,
19062
- components: data[offset + 9]
19063
- };
19064
- }
19065
- const segmentLength = view.getUint16(offset + 2, false);
19066
- offset += 2 + segmentLength;
19067
- }
19068
- throw new Error("Invalid JPEG: SOF marker not found");
19069
- }
19070
19720
 
19071
19721
  //#endregion
19072
19722
  //#region src/utils/pdfValueHelpers.ts
@@ -19809,8 +20459,8 @@ function compressStream(stream, level) {
19809
20459
  * @returns The incremental save result.
19810
20460
  */
19811
20461
  async function saveDocumentIncremental(originalBytes, doc, options) {
19812
- const { buildDocumentStructure } = await import("./pdfCatalog-CTfeeqtF.mjs").then((n) => n.o);
19813
- const { PdfPage: _PdfPage } = await import("./pdfPage-JiCJLV3x.mjs").then((n) => n.r);
20462
+ const { buildDocumentStructure } = await import("./pdfCatalog-BB2Wnmud.mjs").then((n) => n.o);
20463
+ const { PdfPage: _PdfPage } = await import("./pdfPage-N1K2U3jI.mjs").then((n) => n.r);
19814
20464
  const registry = doc.getRegistry();
19815
20465
  const structure = buildDocumentStructure(doc.getInternalPages().map((p) => p.finalize()), {
19816
20466
  producer: doc.getProducer(),
@@ -21917,6 +22567,19 @@ var TokenType = /* @__PURE__ */ function(TokenType) {
21917
22567
  return TokenType;
21918
22568
  }(TokenType || {});
21919
22569
  /**
22570
+ * `hexVal[b]` is the numeric value (0-15) of a hex character, or -1 if
22571
+ * the byte is not a valid hex digit.
22572
+ */
22573
+ const hexVal = /* @__PURE__ */ (() => {
22574
+ const t = new Int8Array(256).fill(-1);
22575
+ for (let i = 0; i <= 9; i++) t[48 + i] = i;
22576
+ for (let i = 0; i < 6; i++) {
22577
+ t[65 + i] = 10 + i;
22578
+ t[97 + i] = 10 + i;
22579
+ }
22580
+ return t;
22581
+ })();
22582
+ /**
21920
22583
  * Combined lexer + parser for PDF content streams.
21921
22584
  *
21922
22585
  * Content streams are simpler than full PDF object syntax — there are no
@@ -22035,20 +22698,22 @@ var ContentStreamLexer = class {
22035
22698
  }
22036
22699
  const dataStart = this.pos;
22037
22700
  let dataEnd = this.pos;
22038
- while (this.pos < this.data.length) {
22039
- if (this.isWhitespace(this.data[this.pos])) {
22040
- const wsPos = this.pos;
22041
- let probe = wsPos + 1;
22042
- if (probe + 1 < this.data.length && this.data[probe] === 69 && this.data[probe + 1] === 73) {
22043
- const afterEI = probe + 2;
22044
- if (afterEI >= this.data.length || this.isWhitespace(this.data[afterEI])) {
22045
- dataEnd = wsPos;
22046
- this.pos = afterEI;
22047
- break;
22048
- }
22701
+ let searchFrom = this.pos;
22702
+ while (searchFrom < this.data.length) {
22703
+ const eIdx = this.data.indexOf(69, searchFrom);
22704
+ if (eIdx === -1 || eIdx + 1 >= this.data.length) {
22705
+ this.pos = this.data.length;
22706
+ break;
22707
+ }
22708
+ if (eIdx > dataStart && this.isWhitespace(this.data[eIdx - 1]) && this.data[eIdx + 1] === 73) {
22709
+ const afterEI = eIdx + 2;
22710
+ if (afterEI >= this.data.length || this.isWhitespace(this.data[afterEI])) {
22711
+ dataEnd = eIdx - 1;
22712
+ this.pos = afterEI;
22713
+ break;
22049
22714
  }
22050
22715
  }
22051
- this.pos++;
22716
+ searchFrom = eIdx + 1;
22052
22717
  }
22053
22718
  return {
22054
22719
  dict,
@@ -22116,7 +22781,7 @@ var ContentStreamLexer = class {
22116
22781
  */
22117
22782
  readLiteralString() {
22118
22783
  this.pos++;
22119
- let result = "";
22784
+ const parts = [];
22120
22785
  let depth = 1;
22121
22786
  while (this.pos < this.data.length && depth > 0) {
22122
22787
  const ch = this.data[this.pos];
@@ -22126,35 +22791,35 @@ var ContentStreamLexer = class {
22126
22791
  const esc = this.data[this.pos];
22127
22792
  switch (esc) {
22128
22793
  case 110:
22129
- result += "\n";
22794
+ parts.push("\n");
22130
22795
  this.pos++;
22131
22796
  break;
22132
22797
  case 114:
22133
- result += "\r";
22798
+ parts.push("\r");
22134
22799
  this.pos++;
22135
22800
  break;
22136
22801
  case 116:
22137
- result += " ";
22802
+ parts.push(" ");
22138
22803
  this.pos++;
22139
22804
  break;
22140
22805
  case 98:
22141
- result += "\b";
22806
+ parts.push("\b");
22142
22807
  this.pos++;
22143
22808
  break;
22144
22809
  case 102:
22145
- result += "\f";
22810
+ parts.push("\f");
22146
22811
  this.pos++;
22147
22812
  break;
22148
22813
  case 40:
22149
- result += "(";
22814
+ parts.push("(");
22150
22815
  this.pos++;
22151
22816
  break;
22152
22817
  case 41:
22153
- result += ")";
22818
+ parts.push(")");
22154
22819
  this.pos++;
22155
22820
  break;
22156
22821
  case 92:
22157
- result += "\\";
22822
+ parts.push("\\");
22158
22823
  this.pos++;
22159
22824
  break;
22160
22825
  case 10:
@@ -22182,29 +22847,29 @@ var ContentStreamLexer = class {
22182
22847
  }
22183
22848
  }
22184
22849
  }
22185
- result += String.fromCharCode(octal & 255);
22850
+ parts.push(String.fromCharCode(octal & 255));
22186
22851
  } else {
22187
- result += String.fromCharCode(esc);
22852
+ parts.push(String.fromCharCode(esc));
22188
22853
  this.pos++;
22189
22854
  }
22190
22855
  break;
22191
22856
  }
22192
22857
  } else if (ch === 40) {
22193
22858
  depth++;
22194
- result += "(";
22859
+ parts.push("(");
22195
22860
  this.pos++;
22196
22861
  } else if (ch === 41) {
22197
22862
  depth--;
22198
- if (depth > 0) result += ")";
22863
+ if (depth > 0) parts.push(")");
22199
22864
  this.pos++;
22200
22865
  } else {
22201
- result += String.fromCharCode(ch);
22866
+ parts.push(String.fromCharCode(ch));
22202
22867
  this.pos++;
22203
22868
  }
22204
22869
  }
22205
22870
  return {
22206
22871
  type: TokenType.String,
22207
- value: result
22872
+ value: parts.join("")
22208
22873
  };
22209
22874
  }
22210
22875
  /**
@@ -22212,7 +22877,8 @@ var ContentStreamLexer = class {
22212
22877
  */
22213
22878
  readHexString() {
22214
22879
  this.pos++;
22215
- let hex = "";
22880
+ const bytes = [];
22881
+ let hi = -1;
22216
22882
  while (this.pos < this.data.length) {
22217
22883
  const ch = this.data[this.pos];
22218
22884
  if (ch === 62) {
@@ -22223,18 +22889,22 @@ var ContentStreamLexer = class {
22223
22889
  this.pos++;
22224
22890
  continue;
22225
22891
  }
22226
- hex += String.fromCharCode(ch);
22892
+ const v = hexVal[ch];
22893
+ if (v === -1) {
22894
+ this.pos++;
22895
+ continue;
22896
+ }
22897
+ if (hi === -1) hi = v;
22898
+ else {
22899
+ bytes.push(hi << 4 | v);
22900
+ hi = -1;
22901
+ }
22227
22902
  this.pos++;
22228
22903
  }
22229
- if (hex.length % 2 !== 0) hex += "0";
22230
- let result = "";
22231
- for (let i = 0; i < hex.length; i += 2) {
22232
- const byte = parseInt(hex.substring(i, i + 2), 16);
22233
- if (!isNaN(byte)) result += String.fromCharCode(byte);
22234
- }
22904
+ if (hi !== -1) bytes.push(hi << 4);
22235
22905
  return {
22236
22906
  type: TokenType.HexString,
22237
- value: result
22907
+ value: String.fromCharCode.apply(null, bytes)
22238
22908
  };
22239
22909
  }
22240
22910
  /**
@@ -22242,27 +22912,25 @@ var ContentStreamLexer = class {
22242
22912
  */
22243
22913
  readName() {
22244
22914
  this.pos++;
22245
- let name = "/";
22915
+ const parts = ["/"];
22246
22916
  while (this.pos < this.data.length) {
22247
22917
  const ch = this.data[this.pos];
22248
22918
  if (this.isWhitespace(ch) || this.isDelimiter(ch)) break;
22249
22919
  if (ch === 35 && this.pos + 2 < this.data.length) {
22250
- const hi = this.data[this.pos + 1];
22251
- const lo = this.data[this.pos + 2];
22252
- const hex = String.fromCharCode(hi) + String.fromCharCode(lo);
22253
- const code = parseInt(hex, 16);
22254
- if (!isNaN(code)) {
22255
- name += String.fromCharCode(code);
22920
+ const hi = hexVal[this.data[this.pos + 1]];
22921
+ const lo = hexVal[this.data[this.pos + 2]];
22922
+ if (hi !== -1 && lo !== -1) {
22923
+ parts.push(String.fromCharCode(hi << 4 | lo));
22256
22924
  this.pos += 3;
22257
22925
  continue;
22258
22926
  }
22259
22927
  }
22260
- name += String.fromCharCode(ch);
22928
+ parts.push(String.fromCharCode(ch));
22261
22929
  this.pos++;
22262
22930
  }
22263
22931
  return {
22264
22932
  type: TokenType.Name,
22265
- value: PdfName.of(name)
22933
+ value: PdfName.of(parts.join(""))
22266
22934
  };
22267
22935
  }
22268
22936
  /**
@@ -22356,9 +23024,7 @@ var ContentStreamLexer = class {
22356
23024
  * Decode a slice of the data as ASCII text.
22357
23025
  */
22358
23026
  decodeAscii(start, end) {
22359
- let s = "";
22360
- for (let i = start; i < end; i++) s += String.fromCharCode(this.data[i]);
22361
- return s;
23027
+ return String.fromCharCode.apply(null, this.data.subarray(start, end));
22362
23028
  }
22363
23029
  };
22364
23030
 
@@ -23354,10 +24020,10 @@ async function initWasm(options) {
23354
24020
  if (options === void 0 || typeof options === "string" || options instanceof URL) return;
23355
24021
  if (wasmInitialized) return;
23356
24022
  const inits = [];
23357
- if (options.deflate || options.deflateWasm) inits.push(import("./libdeflateWasm-CRFwmrSl.mjs").then((n) => n.r).then(async ({ initDeflateWasm }) => {
24023
+ if (options.deflate || options.deflateWasm) inits.push(import("./libdeflateWasm-DlHgU5oy.mjs").then((n) => n.r).then(async ({ initDeflateWasm }) => {
23358
24024
  await initDeflateWasm(options.deflateWasm);
23359
24025
  }));
23360
- if (options.png || options.pngWasm) inits.push(import("./pngEmbed-CHyesD7i.mjs").then((n) => n.n).then(async ({ initPngWasm }) => {
24026
+ if (options.png || options.pngWasm) inits.push(import("./pngEmbed-DTOqgEUC.mjs").then((n) => n.n).then(async ({ initPngWasm }) => {
23361
24027
  await initPngWasm(options.pngWasm);
23362
24028
  }));
23363
24029
  if (options.fonts || options.fontWasm) inits.push(import("./fontSubset-ZpLoOZ2e.mjs").then((n) => n.r).then(async ({ initSubsetWasm }) => {
@@ -23368,5 +24034,5 @@ async function initWasm(options) {
23368
24034
  }
23369
24035
 
23370
24036
  //#endregion
23371
- export { AnnotationFlags, BlendMode, ChangeTracker, CombedTextLayoutError, EmbeddedFont, EncryptedPdfError, ExceededMaxLengthError, FieldAlreadyExistsError, FieldExistsAsNonTerminalError, FieldFlags, FontNotEmbeddedError, ForeignPageError, ImageAlignment, InvalidFieldNamePartError, LineCapStyle, LineJoinStyle, MissingOnValueCheckError, NoSuchFieldError, PDFOperator, PageSizes, ParseSpeeds, PdfAnnotation, PdfArray, PdfBool, PdfButtonField, PdfCheckboxField, PdfCircleAnnotation, PdfDict, PdfDocument, PdfDropdownField, PdfEncryptionHandler, PdfField, PdfForm, PdfFreeTextAnnotation, PdfHighlightAnnotation, PdfInkAnnotation, PdfLayer, PdfLayerManager, PdfLineAnnotation, PdfLinkAnnotation, PdfListboxField, PdfName, PdfNull, PdfNumber, PdfObjectRegistry, PdfOutlineItem, PdfOutlineTree, PdfPage, PdfPolyLineAnnotation, PdfPolygonAnnotation, PdfRadioGroup, PdfRedactAnnotation, PdfRef, PdfSignatureField, PdfSquareAnnotation, PdfSquigglyAnnotation, PdfStampAnnotation, PdfStream, PdfStreamWriter, PdfStrikeOutAnnotation, PdfString, PdfStructureElement, PdfStructureTree, PdfTextAnnotation, PdfTextField, PdfUnderlineAnnotation, PdfViewerPreferences, PdfWriter, RemovePageFromEmptyDocumentError, RichTextFieldReadError, StandardFonts, TextAlignment, TextRenderingMode, UnexpectedFieldTypeError, addWatermark, addWatermarkToPage, aesDecryptCBC, aesEncryptCBC, annotationFromDict, applyFillColor, applyRedactions, applyStrokeColor, asNumber, asPDFName, asPDFNumber, attachFile, base64Decode, base64Encode, beginArtifact, beginArtifactWithType, beginLayerContent, beginMarkedContent, beginMarkedContentSequence, beginMarkedContentWithProperties, beginText, buildAnnotationDict, buildCatalog, buildDocumentStructure, buildEmbeddedFilesNameTree, buildInfoDict, buildPageTree, buildPkcs7Signature, buildTimestampRequest, buildViewerPreferencesDict, buildXmpMetadata, checkAccessibility, circlePath, clipEvenOdd, clip as clipOp, closeAndStroke, closeFillAndStroke, closeFillEvenOddAndStroke, closePath as closePathOp, cmyk, colorToComponents, componentsToColor, computeFileEncryptionKey, computeFontSize, computeSignatureHash, concatMatrix, concatMatrix as concatTransformationMatrix, copyPages, createAnnotation, createMarkedContentScope, createPdf, createXmpStream, cropPage, curveToFinal, curveToInitial, curveTo as curveToOp, decodePermissions, decodeStream, degrees, degreesToRadians, drawImageWithMatrix, drawImageXObject, drawXObject as drawObject, drawXObject, drawSvgOnPage, ellipsePath, embedPageAsFormXObject, embedSignature, encodeContextTag, encodeInteger, encodeLength, encodeOID, encodeOctetString, encodePermissions, encodePrintableString, encodeSequence, encodeSet, encodeUTCTime, encodeUtf8String, endArtifact, endLayerContent, endMarkedContent, endPath as endPathOp, endText, enforcePdfA, extractMetrics, extractText, extractTextWithPositions, fillAndStroke as fillAndStrokeOp, fillEvenOdd, fillEvenOddAndStroke, fill as fillOp, findSignatures, formatPdfDate, generateButtonAppearance, generateCheckboxAppearance, generateCircleAppearance, generateDropdownAppearance, generateFreeTextAppearance, generateHighlightAppearance, generateInkAppearance, generateLineAppearance, generateListboxAppearance, generateRadioAppearance, generateSignatureAppearance, generateSquareAppearance, generateSquigglyAppearance, generateStrikeOutAppearance, generateTextAppearance, generateUnderlineAppearance, getAttachments, getPageSize, getRedactionMarks, getSignatures, grayscale, initWasm, insertPage, isAccessible, isLinearized, isOpenTypeCFF, isTrueType, layoutCombedText, layoutMultilineText, layoutSinglelineText, lineTo as lineToOp, linearizePdf, loadPdf, markForRedaction, md5, mergePdfs, movePage, moveText as moveTextOp, moveTextSetLeading, moveTo as moveToOp, nextLine as nextLineOp, parseContentStream, parseSvg, parseSvgColor, parseSvgPath, parseSvgTransform, parseTimestampResponse, parseViewerPreferences, parseXmpMetadata, restoreState as popGraphicsState, restoreState, prepareForSigning, saveState as pushGraphicsState, saveState, radians, radiansToDegrees, rc4, rectangle as rectangleOp, removePage, removePages, requestTimestamp, resizePage, reversePages, rgb, rotateAllPages, rotate as rotateOp, rotatePage, rotationMatrix, saveDocumentIncremental, saveIncremental, scale as scaleOp, serializePdf, setCharacterSpacing as setCharacterSpacingOp, setCharacterSpacing as setCharacterSqueeze, setColorSpace, setDashPattern as setDashPatternOp, setFillColor, setFillColorCmyk, setFillColorGray, setFillColorRgb, setFillingColor, setFlatness, setFont as setFontAndSize, setFont as setFontOp, setFontSize as setFontSizeOp, setGraphicsState as setGraphicsStateOp, setLeading as setLeadingOp, setLeading as setLineHeight, setLineCap as setLineCapOp, setLineJoin as setLineJoinOp, setLineWidth as setLineWidthOp, setMiterLimit, setStrokeColor, setStrokeColorCmyk, setStrokeColorGray, setStrokeColorRgb, setStrokeColorSpace, setStrokingColor, setTextMatrix as setTextMatrixOp, setTextRenderingMode as setTextRenderingModeOp, setTextRise as setTextRiseOp, setWordSpacing as setWordSpacingOp, sha256, sha384, sha512, showTextArray, showTextHex, showTextNextLine, showText as showTextOp, showTextWithSpacing, signPdf, skew as skewOp, splitPdf, stroke as strokeOp, summarizeIssues, svgToPdfOperators, translate as translateOp, validatePdfA, verifyOwnerPassword, verifySignature, verifySignatures, verifyUserPassword, wrapInMarkedContent };
24037
+ export { AnnotationFlags, BlendMode, ChangeTracker, CombedTextLayoutError, EmbeddedFont, EncryptedPdfError, ExceededMaxLengthError, FieldAlreadyExistsError, FieldExistsAsNonTerminalError, FieldFlags, FontNotEmbeddedError, ForeignPageError, ImageAlignment, InvalidFieldNamePartError, LineCapStyle, LineJoinStyle, MissingOnValueCheckError, NoSuchFieldError, PDFOperator, PageSizes, ParseSpeeds, PdfAnnotation, PdfArray, PdfBool, PdfButtonField, PdfCheckboxField, PdfCircleAnnotation, PdfDict, PdfDocument, PdfDropdownField, PdfEncryptionHandler, PdfField, PdfForm, PdfFreeTextAnnotation, PdfHighlightAnnotation, PdfInkAnnotation, PdfLayer, PdfLayerManager, PdfLineAnnotation, PdfLinkAnnotation, PdfListboxField, PdfName, PdfNull, PdfNumber, PdfObjectRegistry, PdfOutlineItem, PdfOutlineTree, PdfPage, PdfParseError, PdfPolyLineAnnotation, PdfPolygonAnnotation, PdfRadioGroup, PdfRedactAnnotation, PdfRef, PdfSignatureField, PdfSquareAnnotation, PdfSquigglyAnnotation, PdfStampAnnotation, PdfStream, PdfStreamWriter, PdfStrikeOutAnnotation, PdfString, PdfStructureElement, PdfStructureTree, PdfTextAnnotation, PdfTextField, PdfUnderlineAnnotation, PdfViewerPreferences, PdfWriter, RemovePageFromEmptyDocumentError, RichTextFieldReadError, StandardFonts, TextAlignment, TextRenderingMode, UnexpectedFieldTypeError, addWatermark, addWatermarkToPage, aesDecryptCBC, aesEncryptCBC, annotationFromDict, applyFillColor, applyRedactions, applyStrokeColor, asNumber, asPDFName, asPDFNumber, attachFile, base64Decode, base64Encode, beginArtifact, beginArtifactWithType, beginLayerContent, beginMarkedContent, beginMarkedContentSequence, beginMarkedContentWithProperties, beginText, buildAnnotationDict, buildCatalog, buildDocumentStructure, buildEmbeddedFilesNameTree, buildGradientObjects, buildInfoDict, buildPageTree, buildPatternObjects, buildPkcs7Signature, buildTimestampRequest, buildViewerPreferencesDict, buildXmpMetadata, checkAccessibility, circlePath, clipEvenOdd, clip as clipOp, closeAndStroke, closeFillAndStroke, closeFillEvenOddAndStroke, closePath as closePathOp, cmyk, colorToComponents, componentsToColor, computeFileEncryptionKey, computeFontSize, computeSignatureHash, concatMatrix, concatMatrix as concatTransformationMatrix, copyPages, createAnnotation, createMarkedContentScope, createPdf, createXmpStream, cropPage, curveToFinal, curveToInitial, curveTo as curveToOp, decodePermissions, decodeStream, degrees, degreesToRadians, drawImageWithMatrix, drawImageXObject, drawXObject as drawObject, drawXObject, drawSvgOnPage, ellipsePath, embedPageAsFormXObject, embedSignature, encodeContextTag, encodeInteger, encodeLength, encodeOID, encodeOctetString, encodePermissions, encodePrintableString, encodeSequence, encodeSet, encodeUTCTime, encodeUtf8String, endArtifact, endLayerContent, endMarkedContent, endPath as endPathOp, endText, enforcePdfA, extractMetrics, extractText, extractTextWithPositions, fillAndStroke as fillAndStrokeOp, fillEvenOdd, fillEvenOddAndStroke, fill as fillOp, findSignatures, formatHexContext, formatPdfDate, generateButtonAppearance, generateCheckboxAppearance, generateCircleAppearance, generateDropdownAppearance, generateFreeTextAppearance, generateHighlightAppearance, generateInkAppearance, generateLineAppearance, generateListboxAppearance, generateRadioAppearance, generateSignatureAppearance, generateSquareAppearance, generateSquigglyAppearance, generateStrikeOutAppearance, generateTextAppearance, generateUnderlineAppearance, getAttachments, getPageSize, getRedactionMarks, getSignatures, grayscale, initWasm, insertPage, isAccessible, isLinearized, isOpenTypeCFF, isTrueType, layoutCombedText, layoutMultilineText, layoutSinglelineText, lineTo as lineToOp, linearGradient, linearizePdf, loadPdf, markForRedaction, md5, mergePdfs, movePage, moveText as moveTextOp, moveTextSetLeading, moveTo as moveToOp, nextLine as nextLineOp, parseContentStream, parseSvg, parseSvgColor, parseSvgPath, parseSvgTransform, parseTimestampResponse, parseViewerPreferences, parseXmpMetadata, restoreState as popGraphicsState, restoreState, prepareForSigning, saveState as pushGraphicsState, saveState, radialGradient, radians, radiansToDegrees, rc4, rectangle as rectangleOp, removePage, removePages, requestTimestamp, resizePage, reversePages, rgb, rotateAllPages, rotate as rotateOp, rotatePage, rotationMatrix, saveDocumentIncremental, saveIncremental, scale as scaleOp, serializePdf, setCharacterSpacing as setCharacterSpacingOp, setCharacterSpacing as setCharacterSqueeze, setColorSpace, setDashPattern as setDashPatternOp, setFillColor, setFillColorCmyk, setFillColorGray, setFillColorRgb, setFillingColor, setFlatness, setFont as setFontAndSize, setFont as setFontOp, setFontSize as setFontSizeOp, setGraphicsState as setGraphicsStateOp, setLeading as setLeadingOp, setLeading as setLineHeight, setLineCap as setLineCapOp, setLineJoin as setLineJoinOp, setLineWidth as setLineWidthOp, setMiterLimit, setStrokeColor, setStrokeColorCmyk, setStrokeColorGray, setStrokeColorRgb, setStrokeColorSpace, setStrokingColor, setTextMatrix as setTextMatrixOp, setTextRenderingMode as setTextRenderingModeOp, setTextRise as setTextRiseOp, setWordSpacing as setWordSpacingOp, sha256, sha384, sha512, showTextArray, showTextHex, showTextNextLine, showText as showTextOp, showTextWithSpacing, signPdf, skew as skewOp, splitPdf, stroke as strokeOp, summarizeIssues, svgToPdfOperators, tilingPattern, translate as translateOp, validatePdfA, verifyOwnerPassword, verifySignature, verifySignatures, verifyUserPassword, wrapInMarkedContent };
23372
24038
  //# sourceMappingURL=index.mjs.map