@poe-platform/safe-bash 0.1.757 → 0.1.759

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/image-ast/index.browser.js +87 -24
  2. package/dist/image-ast/index.js +87 -24
  3. package/dist/pdf-ast/ast.d.ts +3 -0
  4. package/dist/pdf-ast/index.js +103 -41
  5. package/dist/safe-bash/chunks/{chunk-WNWIBBJZ.js → chunk-AYPUGSOV.js} +7 -1
  6. package/dist/safe-bash/command-chunks/{chunk-F3J5ZLKF.js → chunk-522TDVLS.js} +1 -1
  7. package/dist/safe-bash/command-chunks/{chunk-VFS2MDAB.js → chunk-6YLD37NH.js} +2 -2
  8. package/dist/safe-bash/command-chunks/{chunk-YI3GKJ7Q.js → chunk-766IWMTB.js} +2 -2
  9. package/dist/safe-bash/command-chunks/{chunk-WI35236J.js → chunk-7JA44PVV.js} +1 -1
  10. package/dist/safe-bash/command-chunks/{chunk-H2FQA4OU.js → chunk-BAUGDXLZ.js} +87 -25
  11. package/dist/safe-bash/command-chunks/{chunk-KSH2F6RG.js → chunk-CUFCNL6G.js} +1 -1
  12. package/dist/safe-bash/command-chunks/{chunk-KBBI4CSU.js → chunk-HVEAK3OS.js} +2 -2
  13. package/dist/safe-bash/command-chunks/{chunk-S4MLIYSN.js → chunk-J2NPH7DO.js} +4 -0
  14. package/dist/safe-bash/command-chunks/{chunk-4F6PG2OT.js → chunk-YJWWRCIG.js} +8 -8
  15. package/dist/safe-bash/commands/python/index.browser.js +1 -1
  16. package/dist/safe-bash/commands/python/shell-capability.js +10 -2
  17. package/dist/safe-bash/core.browser.js +1 -1
  18. package/dist/safe-bash-command-column/column.js +3 -3
  19. package/dist/safe-bash-command-column/index.js +3 -3
  20. package/dist/safe-bash-command-column/layout.js +2 -2
  21. package/dist/safe-bash-command-factor/command.js +2 -2
  22. package/dist/safe-bash-command-factor/index.js +2 -2
  23. package/dist/safe-bash-command-ffmpeg/index.js +6300 -6265
  24. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  25. package/dist/safe-bash-command-pandoc/command.js +3 -3
  26. package/dist/safe-bash-command-pandoc/index.js +3 -3
  27. package/dist/safe-bash-command-pdfimages/index.js +87 -24
  28. package/dist/safe-bash-command-pdfinfo/index.js +103 -41
  29. package/dist/safe-bash-command-pdftk/index.js +87 -24
  30. package/dist/safe-bash-command-pdftoppm/index.js +103 -41
  31. package/dist/safe-bash-command-pdftotext/index.js +87 -24
  32. package/dist/safe-bash-command-qpdf/index.js +87 -24
  33. package/dist/safe-bash-command-sips/index.js +2 -2
  34. package/dist/safe-bash-command-soffice/index.js +2 -2
  35. package/dist/safe-bash-command-ssconvert/command-bindings.d.ts +18 -0
  36. package/dist/safe-bash-command-ssconvert/command.d.ts +5 -14
  37. package/dist/safe-bash-command-ssconvert/commands.d.ts +6 -0
  38. package/dist/safe-bash-command-ssconvert/commands.js +871 -0
  39. package/dist/safe-bash-command-ssconvert/core.js +1 -1
  40. package/dist/safe-bash-command-ssconvert/index.js +306 -236
  41. package/dist/safe-bash-command-wkhtmltopdf/index.js +88 -24
  42. package/dist/safe-bash-command-yq/index.js +4 -4
  43. package/dist/safe-bash-compression-engine/files.js +2 -2
  44. package/dist/safe-bash-compression-engine/operand.js +4 -4
  45. package/dist/safe-bash-markdown-engine/commonmark-blocks.js +4 -4
  46. package/dist/safe-bash-markdown-engine/commonmark-inlines.js +4 -4
  47. package/dist/safe-bash-markdown-engine/commonmark-syntax.js +2 -2
  48. package/dist/safe-bash-markdown-engine/gfm-syntax.js +3 -3
  49. package/dist/safe-bash-markdown-engine/index.js +7 -7
  50. package/dist/safe-bash-query-engine/index.js +5 -5
  51. package/dist/safe-bash-query-engine/interpreter.js +4 -4
  52. package/dist/safe-bash-query-engine/query-core.js +5 -5
  53. package/package.json +6 -2
  54. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +30 -0
  55. package/dist/safe-bash/command-chunks/{chunk-OQVIJMBY.js → chunk-7HINP7ZK.js} +4 -4
  56. package/dist/safe-bash/command-chunks/{chunk-XAYEDOV5.js → chunk-CG4JSOK2.js} +3 -3
  57. package/dist/safe-bash/command-chunks/{chunk-YIK4ZYQ4.js → chunk-DC52GWRK.js} +9 -9
  58. package/dist/safe-bash/command-chunks/{chunk-TOTZFBDT.js → chunk-TKACIO4X.js} +4 -4
  59. package/dist/safe-bash/command-chunks/{chunk-VTWKS4RM.js → chunk-WF2LSKMI.js} +3 -3
@@ -8654,6 +8654,7 @@ var messages_default2 = {
8654
8654
  "-5": "buffer error",
8655
8655
  "-6": "incompatible version"
8656
8656
  };
8657
+ var Z_BUF_ERROR = -5;
8657
8658
  var MAX_MEM_LEVEL2 = 9;
8658
8659
  var HEAP_SIZE2 = 573;
8659
8660
  var MIN_MATCH2 = 3;
@@ -30545,22 +30546,31 @@ function decodeFlate(bytes, parms, maxDecodedBytes = DEFAULT_MAX_DECODED_BYTES)
30545
30546
  inflated = new BoundedFlateStream(bytes, maxDecodedBytes).getBytes();
30546
30547
  } catch (error) {
30547
30548
  if (error instanceof PdfError && error.code === "E_LIMIT") throw error;
30549
+ const wrapped = bytes[0] === 31 && bytes[1] === 139 || bytes.length >= 2 && (bytes[0] & 15) === 8 && bytes[0] >>> 4 <= 7 && (bytes[0] << 8 | bytes[1]) % 31 === 0;
30548
30550
  const decoder = new Inflate2({
30549
- raw: !(bytes[0] === 31 && bytes[1] === 139),
30551
+ raw: !wrapped,
30550
30552
  chunkSize: Math.max(1, Math.min(64 * 1024, maxDecodedBytes + 1))
30551
30553
  });
30554
+ const chunks = [];
30552
30555
  let length = 0;
30553
30556
  decoder.onData = (chunk) => {
30554
30557
  length += chunk.length;
30555
30558
  if (length > maxDecodedBytes) {
30556
30559
  throw new PdfError("E_LIMIT", "FlateDecode output exceeds maximum decoded byte budget");
30557
30560
  }
30558
- decoder.chunks.push(chunk);
30561
+ chunks.push(chunk);
30559
30562
  };
30560
- if (!decoder.push(bytes, true) || decoder.err || !decoder.ended) {
30563
+ const complete2 = decoder.push(bytes, true);
30564
+ const truncated = wrapped && decoder.err === Z_BUF_ERROR && length > 0;
30565
+ if ((!complete2 || decoder.err || !decoder.ended) && !truncated) {
30561
30566
  throw new PdfError("E_CAPABILITY", "Invalid FlateDecode compressed stream");
30562
30567
  }
30563
- inflated = decoder.result;
30568
+ inflated = new Uint8Array(length);
30569
+ let offset = 0;
30570
+ for (const chunk of chunks) {
30571
+ inflated.set(chunk, offset);
30572
+ offset += chunk.length;
30573
+ }
30564
30574
  }
30565
30575
  return applyPredictor(inflated, parms);
30566
30576
  }
@@ -33272,7 +33282,7 @@ var ParsedCosDocument = class {
33272
33282
  return void 0;
33273
33283
  }
33274
33284
  };
33275
- function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false) {
33285
+ function parseNodeFromLexer(lexer, bytes, maxDepth, repair = false) {
33276
33286
  const stack = [];
33277
33287
  while (true) {
33278
33288
  const tok = lexer.nextToken();
@@ -33281,7 +33291,7 @@ function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false)
33281
33291
  if (!parent) return void 0;
33282
33292
  throw new PdfError("E_PARSE", parent.kind === "array" ? "Unterminated PDF array" : "Unterminated PDF dictionary");
33283
33293
  }
33284
- if (!parent && recoverEmptyObject && tok.kind === "keyword" && tok.value === "endobj") {
33294
+ if (!parent && repair && tok.kind === "keyword" && tok.value === "endobj") {
33285
33295
  return { kind: "null", span: tok.span };
33286
33296
  }
33287
33297
  let node;
@@ -33296,6 +33306,7 @@ function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false)
33296
33306
  parent.key = { kind: "name", rawBytes: tok.rawBytes, decoded: tok.decoded, span: tok.span };
33297
33307
  continue;
33298
33308
  } else {
33309
+ if (repair) continue;
33299
33310
  throw new PdfError("E_PARSE", `Expected dictionary key /Name, got ${tok.kind}`);
33300
33311
  }
33301
33312
  } else {
@@ -33464,7 +33475,7 @@ function parseHeaderVersion(bytes) {
33464
33475
  }
33465
33476
  return head.slice(idx + 5, idx + 8);
33466
33477
  }
33467
- function parseObjectAtOffset(bytes, offset, maxRecursionDepth, recoverEmptyObject = false) {
33478
+ function parseObjectAtOffset(bytes, offset, maxRecursionDepth, repair = false) {
33468
33479
  const lexer = new CosByteLexer(bytes, offset);
33469
33480
  const objNumTok = lexer.nextToken();
33470
33481
  const genNumTok = lexer.nextToken();
@@ -33472,7 +33483,7 @@ function parseObjectAtOffset(bytes, offset, maxRecursionDepth, recoverEmptyObjec
33472
33483
  if (objNumTok?.kind !== "number" || genNumTok?.kind !== "number" || objKwTok?.kind !== "keyword" || objKwTok.value !== "obj") {
33473
33484
  throw new PdfError("E_PARSE", `Malformed indirect object header at byte offset ${offset}`);
33474
33485
  }
33475
- const value = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, recoverEmptyObject);
33486
+ const value = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, repair);
33476
33487
  if (!value) {
33477
33488
  throw new PdfError("E_PARSE", `Empty indirect object ${objNumTok.value} at offset ${offset}`);
33478
33489
  }
@@ -33661,7 +33672,7 @@ function repairScanCosDocument(bytes, maxObjects, maxRecursionDepth) {
33661
33672
  try {
33662
33673
  const token = lexer.nextToken();
33663
33674
  if (token?.kind === "keyword" && token.value === "trailer") {
33664
- const trailer = parseNodeFromLexer(lexer, bytes, maxRecursionDepth);
33675
+ const trailer = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, true);
33665
33676
  if (trailer?.kind === "dict") trailers.push(trailer);
33666
33677
  pos = lexer.offset;
33667
33678
  continue;
@@ -33717,7 +33728,7 @@ function unpackRecoveredObjects(objects, maxObjects, maxDecompressedBytes, maxRe
33717
33728
  const t = dictGet(obj.value.dict, "Type");
33718
33729
  if (t?.kind === "name" && t.decoded === "ObjStm") {
33719
33730
  try {
33720
- for (const [unpackedNum, unpackedVal] of unpackObjectStream(obj.value, maxDecompressedBytes, maxRecursionDepth).entries()) {
33731
+ for (const [unpackedNum, unpackedVal] of unpackObjectStream(obj.value, maxDecompressedBytes, maxRecursionDepth, true).entries()) {
33721
33732
  if (!objects.has(unpackedNum)) {
33722
33733
  objects.set(unpackedNum, {
33723
33734
  objectNumber: unpackedNum,
@@ -33753,7 +33764,7 @@ function recoveredReferences(objects) {
33753
33764
  }
33754
33765
  return { ...rootRef ? { rootRef } : {}, ...infoRef ? { infoRef } : {} };
33755
33766
  }
33756
- function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth) {
33767
+ function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth, repair = false) {
33757
33768
  const nNode = dictGet(streamObj.dict, "N");
33758
33769
  const firstNode = dictGet(streamObj.dict, "First");
33759
33770
  if (nNode?.kind !== "number" || firstNode?.kind !== "number") {
@@ -33773,7 +33784,7 @@ function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth)
33773
33784
  for (const pair of pairs) {
33774
33785
  try {
33775
33786
  const valLexer = new CosByteLexer(decoded, firstNode.value + pair.relativeOffset);
33776
- const node = parseNodeFromLexer(valLexer, decoded, maxRecursionDepth);
33787
+ const node = parseNodeFromLexer(valLexer, decoded, maxRecursionDepth, repair);
33777
33788
  if (node) {
33778
33789
  result.set(pair.objectNumber, node);
33779
33790
  }
@@ -33956,7 +33967,7 @@ function parseCosDocument(bytes, options = {}) {
33956
33967
  if (!unpacked) {
33957
33968
  const stmObj = objects.get(entry.objectStreamNumber)?.value;
33958
33969
  if (stmObj?.kind === "stream") {
33959
- unpacked = unpackObjectStream(stmObj, maxDecompressedBytes, maxRecursionDepth);
33970
+ unpacked = unpackObjectStream(stmObj, maxDecompressedBytes, maxRecursionDepth, recovery === "repair");
33960
33971
  objStmCache.set(entry.objectStreamNumber, unpacked);
33961
33972
  }
33962
33973
  }
@@ -42429,7 +42440,11 @@ function resolvePageFonts(doc, resourcesDict) {
42429
42440
  let cmap;
42430
42441
  const toUniNode = doc.resolve(dictGet(fObj, "ToUnicode"));
42431
42442
  if (toUniNode?.kind === "stream") {
42432
- cmap = parseToUnicodeCMap(doc.decodeStream(toUniNode));
42443
+ try {
42444
+ cmap = parseToUnicodeCMap(doc.decodeStream(toUniNode));
42445
+ } catch (error) {
42446
+ if (error instanceof PdfError && error.code === "E_LIMIT") throw error;
42447
+ }
42433
42448
  }
42434
42449
  const encNode = doc.resolve(dictGet(fObj, "Encoding"));
42435
42450
  if (encNode?.kind === "dict") {
@@ -42445,7 +42460,7 @@ function resolvePageFonts(doc, resourcesDict) {
42445
42460
  const glyphNames = buildFontEncodingGlyphNamesMap(encNode);
42446
42461
  const widths = /* @__PURE__ */ new Map();
42447
42462
  let defaultWidth = 556;
42448
- const isTwoByteCid = subtype === "Type0" || Boolean(cmap?.isTwoByte);
42463
+ const isTwoByteCid = subtype === "Type0";
42449
42464
  let fontMatrix;
42450
42465
  let charProcs;
42451
42466
  let fontResources;
@@ -43553,8 +43568,12 @@ function evaluateContentStreamToDisplayList(params) {
43553
43568
  const images = [];
43554
43569
  const operations = [];
43555
43570
  const emit = (operation) => {
43556
- const clipPaths = curState().clipPaths;
43557
- if (clipPaths) operation = { ...operation, value: { ...operation.value, clipPaths } };
43571
+ const { clipPaths, clipImages } = curState();
43572
+ if (clipPaths || clipImages) operation = { ...operation, value: {
43573
+ ...operation.value,
43574
+ ...clipPaths ? { clipPaths } : {},
43575
+ ...clipImages ? { clipImages } : {}
43576
+ } };
43558
43577
  operations.push(operation);
43559
43578
  switch (operation.kind) {
43560
43579
  case "path":
@@ -43818,6 +43837,18 @@ function evaluateContentStreamToDisplayList(params) {
43818
43837
  let hasTextClip = false;
43819
43838
  let activeTm = [1, 0, 0, 1, 0, 0];
43820
43839
  let activeTlm = [1, 0, 0, 1, 0, 0];
43840
+ const paintImage = (image, patternMask, resources, activeFonts, depth) => {
43841
+ if (!patternMask) {
43842
+ emit({ kind: "image", value: image });
43843
+ return;
43844
+ }
43845
+ const st = curState();
43846
+ stateStack.push({ ...st, clipImages: [...st.clipImages ?? [], image] });
43847
+ walkNodes([{ kind: "path-op", paint: "f", segments: [
43848
+ { kind: "rect", x: 0, y: 0, width: 1, height: 1 }
43849
+ ] }], void 0, void 0, resources, activeFonts, depth);
43850
+ stateStack.pop();
43851
+ };
43821
43852
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
43822
43853
  for (const node of nodes) {
43823
43854
  switch (node.kind) {
@@ -44001,7 +44032,8 @@ function evaluateContentStreamToDisplayList(params) {
44001
44032
  st.fillAlpha,
44002
44033
  "PatternShading_" + st.fillPatternName,
44003
44034
  patClip,
44004
- shading?.kind === "stream" ? shading : void 0
44035
+ shading?.kind === "stream" ? shading : void 0,
44036
+ st.blendMode
44005
44037
  );
44006
44038
  if (shImg) {
44007
44039
  emit({ kind: "image", value: shImg });
@@ -44110,18 +44142,20 @@ function evaluateContentStreamToDisplayList(params) {
44110
44142
  const subNode = params.cosDoc.resolve(dictGet(xobjNode.dict, "Subtype"));
44111
44143
  const sub = subNode?.kind === "name" ? subNode.decoded : "";
44112
44144
  if (sub === "Image") {
44145
+ const maskNode = params.cosDoc.resolve(dictGet(xobjNode.dict, "ImageMask"));
44146
+ const patternMask = !!st.fillPatternName && maskNode?.kind === "boolean" && maskNode.value;
44113
44147
  const decoded = decodeXObjectImageToRgba(
44114
44148
  params.cosDoc,
44115
44149
  xobjNode,
44116
44150
  activeResources,
44117
- {
44151
+ patternMask ? { r: 1, g: 1, b: 1, alpha: 1 } : {
44118
44152
  r: st.fillColor.r,
44119
44153
  g: st.fillColor.g,
44120
44154
  b: st.fillColor.b,
44121
44155
  alpha: st.fillAlpha
44122
44156
  }
44123
44157
  );
44124
- emit({ kind: "image", value: {
44158
+ paintImage({
44125
44159
  name: node.name,
44126
44160
  matrix: [...st.ctm],
44127
44161
  width: decoded.width,
@@ -44131,7 +44165,7 @@ function evaluateContentStreamToDisplayList(params) {
44131
44165
  decodedRgba: decoded.rgba,
44132
44166
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
44133
44167
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
44134
- } });
44168
+ }, patternMask, activeResources, activeFonts, depth);
44135
44169
  } else if (sub === "Form" && depth < 8) {
44136
44170
  const formStreamBytes = params.cosDoc.decodeStream(xobjNode);
44137
44171
  const formNodes = parseContentStream(formStreamBytes);
@@ -44187,19 +44221,22 @@ function evaluateContentStreamToDisplayList(params) {
44187
44221
  }
44188
44222
  case "inline-image": {
44189
44223
  const st = curState();
44224
+ const maskEntry = dictGet(node.dict, "ImageMask") ?? dictGet(node.dict, "IM");
44225
+ const maskNode = params.cosDoc ? params.cosDoc.resolve(maskEntry) : maskEntry;
44226
+ const patternMask = !!st.fillPatternName && maskNode?.kind === "boolean" && maskNode.value;
44190
44227
  const decoded = decodeInlineImageNodeToRgba(
44191
44228
  params.cosDoc,
44192
44229
  node.dict,
44193
44230
  node.data,
44194
44231
  activeResources,
44195
- {
44232
+ patternMask ? { r: 1, g: 1, b: 1, alpha: 1 } : {
44196
44233
  r: st.fillColor.r,
44197
44234
  g: st.fillColor.g,
44198
44235
  b: st.fillColor.b,
44199
44236
  alpha: st.fillAlpha
44200
44237
  }
44201
44238
  );
44202
- emit({ kind: "image", value: {
44239
+ paintImage({
44203
44240
  name: "InlineImage",
44204
44241
  matrix: [...st.ctm],
44205
44242
  width: decoded.width,
@@ -44209,7 +44246,7 @@ function evaluateContentStreamToDisplayList(params) {
44209
44246
  decodedRgba: decoded.rgba,
44210
44247
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
44211
44248
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
44212
- } });
44249
+ }, patternMask, activeResources, activeFonts, depth);
44213
44250
  break;
44214
44251
  }
44215
44252
  case "text-object": {
@@ -47559,6 +47596,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47559
47596
  const aaVec = options.antialiasVector !== false;
47560
47597
  const aaTxt = options.antialiasText !== false;
47561
47598
  const clipMasks = /* @__PURE__ */ new Map();
47599
+ const imageClipMasks = /* @__PURE__ */ new Map();
47562
47600
  for (const original of paintOperations(displayList)) {
47563
47601
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
47564
47602
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
@@ -47573,6 +47611,31 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47573
47611
  }
47574
47612
  clipMasks.set(clips, clipMask);
47575
47613
  }
47614
+ const imageClips = original.value.clipImages;
47615
+ if (imageClips) {
47616
+ let imageMask = imageClipMasks.get(imageClips);
47617
+ if (!imageMask) {
47618
+ imageMask = new Uint8Array(width * height * 4).fill(255);
47619
+ for (const image of imageClips) {
47620
+ const layer = renderDisplayListToBitmap({
47621
+ ...displayList,
47622
+ rotation: 0,
47623
+ paths: [],
47624
+ glyphs: [],
47625
+ images: [image],
47626
+ operations: [{ kind: "image", value: image }]
47627
+ }, { scale, transparent: true }).data;
47628
+ for (let i = 3; i < layer.length; i += 4) imageMask[i] = Math.round(imageMask[i] * layer[i] / 255);
47629
+ }
47630
+ imageClipMasks.set(imageClips, imageMask);
47631
+ }
47632
+ if (clipMask) {
47633
+ clipMask = clipMask.slice();
47634
+ for (let i = 3; i < clipMask.length; i += 4) clipMask[i] = Math.round(clipMask[i] * imageMask[i] / 255);
47635
+ } else {
47636
+ clipMask = imageMask;
47637
+ }
47638
+ }
47576
47639
  if (operation.kind === "path") {
47577
47640
  const path = operation.value;
47578
47641
  if (path.fillColor) {
@@ -8654,6 +8654,7 @@ var messages_default2 = {
8654
8654
  "-5": "buffer error",
8655
8655
  "-6": "incompatible version"
8656
8656
  };
8657
+ var Z_BUF_ERROR = -5;
8657
8658
  var MAX_MEM_LEVEL2 = 9;
8658
8659
  var HEAP_SIZE2 = 573;
8659
8660
  var MIN_MATCH2 = 3;
@@ -30545,22 +30546,31 @@ function decodeFlate(bytes, parms, maxDecodedBytes = DEFAULT_MAX_DECODED_BYTES)
30545
30546
  inflated = new BoundedFlateStream(bytes, maxDecodedBytes).getBytes();
30546
30547
  } catch (error) {
30547
30548
  if (error instanceof PdfError && error.code === "E_LIMIT") throw error;
30549
+ const wrapped = bytes[0] === 31 && bytes[1] === 139 || bytes.length >= 2 && (bytes[0] & 15) === 8 && bytes[0] >>> 4 <= 7 && (bytes[0] << 8 | bytes[1]) % 31 === 0;
30548
30550
  const decoder = new Inflate2({
30549
- raw: !(bytes[0] === 31 && bytes[1] === 139),
30551
+ raw: !wrapped,
30550
30552
  chunkSize: Math.max(1, Math.min(64 * 1024, maxDecodedBytes + 1))
30551
30553
  });
30554
+ const chunks = [];
30552
30555
  let length = 0;
30553
30556
  decoder.onData = (chunk) => {
30554
30557
  length += chunk.length;
30555
30558
  if (length > maxDecodedBytes) {
30556
30559
  throw new PdfError("E_LIMIT", "FlateDecode output exceeds maximum decoded byte budget");
30557
30560
  }
30558
- decoder.chunks.push(chunk);
30561
+ chunks.push(chunk);
30559
30562
  };
30560
- if (!decoder.push(bytes, true) || decoder.err || !decoder.ended) {
30563
+ const complete2 = decoder.push(bytes, true);
30564
+ const truncated = wrapped && decoder.err === Z_BUF_ERROR && length > 0;
30565
+ if ((!complete2 || decoder.err || !decoder.ended) && !truncated) {
30561
30566
  throw new PdfError("E_CAPABILITY", "Invalid FlateDecode compressed stream");
30562
30567
  }
30563
- inflated = decoder.result;
30568
+ inflated = new Uint8Array(length);
30569
+ let offset = 0;
30570
+ for (const chunk of chunks) {
30571
+ inflated.set(chunk, offset);
30572
+ offset += chunk.length;
30573
+ }
30564
30574
  }
30565
30575
  return applyPredictor(inflated, parms);
30566
30576
  }
@@ -33272,7 +33282,7 @@ var ParsedCosDocument = class {
33272
33282
  return void 0;
33273
33283
  }
33274
33284
  };
33275
- function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false) {
33285
+ function parseNodeFromLexer(lexer, bytes, maxDepth, repair = false) {
33276
33286
  const stack = [];
33277
33287
  while (true) {
33278
33288
  const tok = lexer.nextToken();
@@ -33281,7 +33291,7 @@ function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false)
33281
33291
  if (!parent) return void 0;
33282
33292
  throw new PdfError("E_PARSE", parent.kind === "array" ? "Unterminated PDF array" : "Unterminated PDF dictionary");
33283
33293
  }
33284
- if (!parent && recoverEmptyObject && tok.kind === "keyword" && tok.value === "endobj") {
33294
+ if (!parent && repair && tok.kind === "keyword" && tok.value === "endobj") {
33285
33295
  return { kind: "null", span: tok.span };
33286
33296
  }
33287
33297
  let node;
@@ -33296,6 +33306,7 @@ function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false)
33296
33306
  parent.key = { kind: "name", rawBytes: tok.rawBytes, decoded: tok.decoded, span: tok.span };
33297
33307
  continue;
33298
33308
  } else {
33309
+ if (repair) continue;
33299
33310
  throw new PdfError("E_PARSE", `Expected dictionary key /Name, got ${tok.kind}`);
33300
33311
  }
33301
33312
  } else {
@@ -33464,7 +33475,7 @@ function parseHeaderVersion(bytes) {
33464
33475
  }
33465
33476
  return head.slice(idx + 5, idx + 8);
33466
33477
  }
33467
- function parseObjectAtOffset(bytes, offset, maxRecursionDepth, recoverEmptyObject = false) {
33478
+ function parseObjectAtOffset(bytes, offset, maxRecursionDepth, repair = false) {
33468
33479
  const lexer = new CosByteLexer(bytes, offset);
33469
33480
  const objNumTok = lexer.nextToken();
33470
33481
  const genNumTok = lexer.nextToken();
@@ -33472,7 +33483,7 @@ function parseObjectAtOffset(bytes, offset, maxRecursionDepth, recoverEmptyObjec
33472
33483
  if (objNumTok?.kind !== "number" || genNumTok?.kind !== "number" || objKwTok?.kind !== "keyword" || objKwTok.value !== "obj") {
33473
33484
  throw new PdfError("E_PARSE", `Malformed indirect object header at byte offset ${offset}`);
33474
33485
  }
33475
- const value = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, recoverEmptyObject);
33486
+ const value = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, repair);
33476
33487
  if (!value) {
33477
33488
  throw new PdfError("E_PARSE", `Empty indirect object ${objNumTok.value} at offset ${offset}`);
33478
33489
  }
@@ -33661,7 +33672,7 @@ function repairScanCosDocument(bytes, maxObjects, maxRecursionDepth) {
33661
33672
  try {
33662
33673
  const token = lexer.nextToken();
33663
33674
  if (token?.kind === "keyword" && token.value === "trailer") {
33664
- const trailer = parseNodeFromLexer(lexer, bytes, maxRecursionDepth);
33675
+ const trailer = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, true);
33665
33676
  if (trailer?.kind === "dict") trailers.push(trailer);
33666
33677
  pos = lexer.offset;
33667
33678
  continue;
@@ -33717,7 +33728,7 @@ function unpackRecoveredObjects(objects, maxObjects, maxDecompressedBytes, maxRe
33717
33728
  const t = dictGet(obj.value.dict, "Type");
33718
33729
  if (t?.kind === "name" && t.decoded === "ObjStm") {
33719
33730
  try {
33720
- for (const [unpackedNum, unpackedVal] of unpackObjectStream(obj.value, maxDecompressedBytes, maxRecursionDepth).entries()) {
33731
+ for (const [unpackedNum, unpackedVal] of unpackObjectStream(obj.value, maxDecompressedBytes, maxRecursionDepth, true).entries()) {
33721
33732
  if (!objects.has(unpackedNum)) {
33722
33733
  objects.set(unpackedNum, {
33723
33734
  objectNumber: unpackedNum,
@@ -33753,7 +33764,7 @@ function recoveredReferences(objects) {
33753
33764
  }
33754
33765
  return { ...rootRef ? { rootRef } : {}, ...infoRef ? { infoRef } : {} };
33755
33766
  }
33756
- function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth) {
33767
+ function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth, repair = false) {
33757
33768
  const nNode = dictGet(streamObj.dict, "N");
33758
33769
  const firstNode = dictGet(streamObj.dict, "First");
33759
33770
  if (nNode?.kind !== "number" || firstNode?.kind !== "number") {
@@ -33773,7 +33784,7 @@ function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth)
33773
33784
  for (const pair of pairs) {
33774
33785
  try {
33775
33786
  const valLexer = new CosByteLexer(decoded, firstNode.value + pair.relativeOffset);
33776
- const node = parseNodeFromLexer(valLexer, decoded, maxRecursionDepth);
33787
+ const node = parseNodeFromLexer(valLexer, decoded, maxRecursionDepth, repair);
33777
33788
  if (node) {
33778
33789
  result.set(pair.objectNumber, node);
33779
33790
  }
@@ -33956,7 +33967,7 @@ function parseCosDocument(bytes, options = {}) {
33956
33967
  if (!unpacked) {
33957
33968
  const stmObj = objects.get(entry.objectStreamNumber)?.value;
33958
33969
  if (stmObj?.kind === "stream") {
33959
- unpacked = unpackObjectStream(stmObj, maxDecompressedBytes, maxRecursionDepth);
33970
+ unpacked = unpackObjectStream(stmObj, maxDecompressedBytes, maxRecursionDepth, recovery === "repair");
33960
33971
  objStmCache.set(entry.objectStreamNumber, unpacked);
33961
33972
  }
33962
33973
  }
@@ -42429,7 +42440,11 @@ function resolvePageFonts(doc, resourcesDict) {
42429
42440
  let cmap;
42430
42441
  const toUniNode = doc.resolve(dictGet(fObj, "ToUnicode"));
42431
42442
  if (toUniNode?.kind === "stream") {
42432
- cmap = parseToUnicodeCMap(doc.decodeStream(toUniNode));
42443
+ try {
42444
+ cmap = parseToUnicodeCMap(doc.decodeStream(toUniNode));
42445
+ } catch (error) {
42446
+ if (error instanceof PdfError && error.code === "E_LIMIT") throw error;
42447
+ }
42433
42448
  }
42434
42449
  const encNode = doc.resolve(dictGet(fObj, "Encoding"));
42435
42450
  if (encNode?.kind === "dict") {
@@ -42445,7 +42460,7 @@ function resolvePageFonts(doc, resourcesDict) {
42445
42460
  const glyphNames = buildFontEncodingGlyphNamesMap(encNode);
42446
42461
  const widths = /* @__PURE__ */ new Map();
42447
42462
  let defaultWidth = 556;
42448
- const isTwoByteCid = subtype === "Type0" || Boolean(cmap?.isTwoByte);
42463
+ const isTwoByteCid = subtype === "Type0";
42449
42464
  let fontMatrix;
42450
42465
  let charProcs;
42451
42466
  let fontResources;
@@ -43553,8 +43568,12 @@ function evaluateContentStreamToDisplayList(params) {
43553
43568
  const images = [];
43554
43569
  const operations = [];
43555
43570
  const emit = (operation) => {
43556
- const clipPaths = curState().clipPaths;
43557
- if (clipPaths) operation = { ...operation, value: { ...operation.value, clipPaths } };
43571
+ const { clipPaths, clipImages } = curState();
43572
+ if (clipPaths || clipImages) operation = { ...operation, value: {
43573
+ ...operation.value,
43574
+ ...clipPaths ? { clipPaths } : {},
43575
+ ...clipImages ? { clipImages } : {}
43576
+ } };
43558
43577
  operations.push(operation);
43559
43578
  switch (operation.kind) {
43560
43579
  case "path":
@@ -43818,6 +43837,18 @@ function evaluateContentStreamToDisplayList(params) {
43818
43837
  let hasTextClip = false;
43819
43838
  let activeTm = [1, 0, 0, 1, 0, 0];
43820
43839
  let activeTlm = [1, 0, 0, 1, 0, 0];
43840
+ const paintImage = (image, patternMask, resources, activeFonts, depth) => {
43841
+ if (!patternMask) {
43842
+ emit({ kind: "image", value: image });
43843
+ return;
43844
+ }
43845
+ const st = curState();
43846
+ stateStack.push({ ...st, clipImages: [...st.clipImages ?? [], image] });
43847
+ walkNodes([{ kind: "path-op", paint: "f", segments: [
43848
+ { kind: "rect", x: 0, y: 0, width: 1, height: 1 }
43849
+ ] }], void 0, void 0, resources, activeFonts, depth);
43850
+ stateStack.pop();
43851
+ };
43821
43852
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
43822
43853
  for (const node of nodes) {
43823
43854
  switch (node.kind) {
@@ -44001,7 +44032,8 @@ function evaluateContentStreamToDisplayList(params) {
44001
44032
  st.fillAlpha,
44002
44033
  "PatternShading_" + st.fillPatternName,
44003
44034
  patClip,
44004
- shading?.kind === "stream" ? shading : void 0
44035
+ shading?.kind === "stream" ? shading : void 0,
44036
+ st.blendMode
44005
44037
  );
44006
44038
  if (shImg) {
44007
44039
  emit({ kind: "image", value: shImg });
@@ -44110,18 +44142,20 @@ function evaluateContentStreamToDisplayList(params) {
44110
44142
  const subNode = params.cosDoc.resolve(dictGet(xobjNode.dict, "Subtype"));
44111
44143
  const sub = subNode?.kind === "name" ? subNode.decoded : "";
44112
44144
  if (sub === "Image") {
44145
+ const maskNode = params.cosDoc.resolve(dictGet(xobjNode.dict, "ImageMask"));
44146
+ const patternMask = !!st.fillPatternName && maskNode?.kind === "boolean" && maskNode.value;
44113
44147
  const decoded = decodeXObjectImageToRgba(
44114
44148
  params.cosDoc,
44115
44149
  xobjNode,
44116
44150
  activeResources,
44117
- {
44151
+ patternMask ? { r: 1, g: 1, b: 1, alpha: 1 } : {
44118
44152
  r: st.fillColor.r,
44119
44153
  g: st.fillColor.g,
44120
44154
  b: st.fillColor.b,
44121
44155
  alpha: st.fillAlpha
44122
44156
  }
44123
44157
  );
44124
- emit({ kind: "image", value: {
44158
+ paintImage({
44125
44159
  name: node.name,
44126
44160
  matrix: [...st.ctm],
44127
44161
  width: decoded.width,
@@ -44131,7 +44165,7 @@ function evaluateContentStreamToDisplayList(params) {
44131
44165
  decodedRgba: decoded.rgba,
44132
44166
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
44133
44167
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
44134
- } });
44168
+ }, patternMask, activeResources, activeFonts, depth);
44135
44169
  } else if (sub === "Form" && depth < 8) {
44136
44170
  const formStreamBytes = params.cosDoc.decodeStream(xobjNode);
44137
44171
  const formNodes = parseContentStream(formStreamBytes);
@@ -44187,19 +44221,22 @@ function evaluateContentStreamToDisplayList(params) {
44187
44221
  }
44188
44222
  case "inline-image": {
44189
44223
  const st = curState();
44224
+ const maskEntry = dictGet(node.dict, "ImageMask") ?? dictGet(node.dict, "IM");
44225
+ const maskNode = params.cosDoc ? params.cosDoc.resolve(maskEntry) : maskEntry;
44226
+ const patternMask = !!st.fillPatternName && maskNode?.kind === "boolean" && maskNode.value;
44190
44227
  const decoded = decodeInlineImageNodeToRgba(
44191
44228
  params.cosDoc,
44192
44229
  node.dict,
44193
44230
  node.data,
44194
44231
  activeResources,
44195
- {
44232
+ patternMask ? { r: 1, g: 1, b: 1, alpha: 1 } : {
44196
44233
  r: st.fillColor.r,
44197
44234
  g: st.fillColor.g,
44198
44235
  b: st.fillColor.b,
44199
44236
  alpha: st.fillAlpha
44200
44237
  }
44201
44238
  );
44202
- emit({ kind: "image", value: {
44239
+ paintImage({
44203
44240
  name: "InlineImage",
44204
44241
  matrix: [...st.ctm],
44205
44242
  width: decoded.width,
@@ -44209,7 +44246,7 @@ function evaluateContentStreamToDisplayList(params) {
44209
44246
  decodedRgba: decoded.rgba,
44210
44247
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
44211
44248
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
44212
- } });
44249
+ }, patternMask, activeResources, activeFonts, depth);
44213
44250
  break;
44214
44251
  }
44215
44252
  case "text-object": {
@@ -47559,6 +47596,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47559
47596
  const aaVec = options.antialiasVector !== false;
47560
47597
  const aaTxt = options.antialiasText !== false;
47561
47598
  const clipMasks = /* @__PURE__ */ new Map();
47599
+ const imageClipMasks = /* @__PURE__ */ new Map();
47562
47600
  for (const original of paintOperations(displayList)) {
47563
47601
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
47564
47602
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
@@ -47573,6 +47611,31 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47573
47611
  }
47574
47612
  clipMasks.set(clips, clipMask);
47575
47613
  }
47614
+ const imageClips = original.value.clipImages;
47615
+ if (imageClips) {
47616
+ let imageMask = imageClipMasks.get(imageClips);
47617
+ if (!imageMask) {
47618
+ imageMask = new Uint8Array(width * height * 4).fill(255);
47619
+ for (const image of imageClips) {
47620
+ const layer = renderDisplayListToBitmap({
47621
+ ...displayList,
47622
+ rotation: 0,
47623
+ paths: [],
47624
+ glyphs: [],
47625
+ images: [image],
47626
+ operations: [{ kind: "image", value: image }]
47627
+ }, { scale, transparent: true }).data;
47628
+ for (let i = 3; i < layer.length; i += 4) imageMask[i] = Math.round(imageMask[i] * layer[i] / 255);
47629
+ }
47630
+ imageClipMasks.set(imageClips, imageMask);
47631
+ }
47632
+ if (clipMask) {
47633
+ clipMask = clipMask.slice();
47634
+ for (let i = 3; i < clipMask.length; i += 4) clipMask[i] = Math.round(clipMask[i] * imageMask[i] / 255);
47635
+ } else {
47636
+ clipMask = imageMask;
47637
+ }
47638
+ }
47576
47639
  if (operation.kind === "path") {
47577
47640
  const path = operation.value;
47578
47641
  if (path.fillColor) {
@@ -223,6 +223,7 @@ export interface PdfPlacedGlyph {
223
223
  readonly actualText?: string | undefined;
224
224
  readonly blendMode?: string | undefined;
225
225
  readonly clipPaths?: readonly (readonly PdfPathSegment[])[] | undefined;
226
+ readonly clipImages?: readonly PdfEvaluatedImage[] | undefined;
226
227
  readonly clipRect?: readonly [number, number, number, number] | undefined;
227
228
  }
228
229
  export interface PdfEvaluatedPath {
@@ -241,6 +242,7 @@ export interface PdfEvaluatedPath {
241
242
  readonly blendMode?: string | undefined;
242
243
  readonly isClip?: boolean | undefined;
243
244
  readonly clipPaths?: readonly (readonly PdfPathSegment[])[] | undefined;
245
+ readonly clipImages?: readonly PdfEvaluatedImage[] | undefined;
244
246
  readonly clipRect?: readonly [number, number, number, number] | undefined;
245
247
  }
246
248
  export interface PdfEvaluatedImage {
@@ -253,6 +255,7 @@ export interface PdfEvaluatedImage {
253
255
  readonly decodedRgba?: Uint8Array | undefined;
254
256
  readonly blendMode?: string | undefined;
255
257
  readonly clipPaths?: readonly (readonly PdfPathSegment[])[] | undefined;
258
+ readonly clipImages?: readonly PdfEvaluatedImage[] | undefined;
256
259
  readonly clipRect?: readonly [number, number, number, number] | undefined;
257
260
  }
258
261
  export interface PdfLinkAnnotation {