@poe-platform/safe-bash 0.1.812 → 0.1.814

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 (602) hide show
  1. package/dist/audio-ast/id3-source.d.ts +27 -0
  2. package/dist/audio-ast/index.d.ts +4 -0
  3. package/dist/audio-ast/index.js +996 -596
  4. package/dist/audio-ast/mp3-source.d.ts +18 -0
  5. package/dist/audio-ast/ogg-source.d.ts +25 -0
  6. package/dist/audio-ast/ogg-stream-source.d.ts +22 -0
  7. package/dist/image-ast/index.js +139 -9
  8. package/dist/mp4-ast/containers/adapters.d.ts +7 -0
  9. package/dist/mp4-ast/index.d.ts +2 -0
  10. package/dist/mp4-ast/mp4-sample-source.d.ts +52 -0
  11. package/dist/mp4-ast/mp4-source.d.ts +32 -0
  12. package/dist/office-xml/retained-xml-document.d.ts +14 -0
  13. package/dist/pdf-ast/ast.d.ts +2 -0
  14. package/dist/pdf-ast/content/dictionary-cursor.d.ts +15 -0
  15. package/dist/pdf-ast/content/evaluator.d.ts +4 -0
  16. package/dist/pdf-ast/content/range-operator-parser.d.ts +4 -0
  17. package/dist/pdf-ast/content/stored-dictionary.d.ts +10 -0
  18. package/dist/pdf-ast/cos/lexer.d.ts +8 -5
  19. package/dist/pdf-ast/cos/object-reader.d.ts +11 -3
  20. package/dist/pdf-ast/cos/range-parser.d.ts +4 -0
  21. package/dist/pdf-ast/cos/retained-objects.d.ts +1 -0
  22. package/dist/pdf-ast/cos/retained-writer.d.ts +1 -0
  23. package/dist/pdf-ast/cos/value-parser.d.ts +10 -0
  24. package/dist/pdf-ast/edit/retained-append-attachments.d.ts +13 -0
  25. package/dist/pdf-ast/edit/retained-bookmarks.d.ts +13 -0
  26. package/dist/pdf-ast/edit/retained-form-appearances.d.ts +10 -0
  27. package/dist/pdf-ast/edit/retained-graph.d.ts +12 -0
  28. package/dist/pdf-ast/edit/retained-info-updates.d.ts +33 -0
  29. package/dist/pdf-ast/edit/retained-save.d.ts +2 -0
  30. package/dist/pdf-ast/edit/retained-stamps.d.ts +9 -0
  31. package/dist/pdf-ast/fonts/resolve.d.ts +3 -1
  32. package/dist/pdf-ast/index.d.ts +3 -1
  33. package/dist/pdf-ast/index.js +1966 -844
  34. package/dist/pdf-ast/retained-document.d.ts +5 -0
  35. package/dist/safe-bash/audio-ast.browser.js +6 -1
  36. package/dist/safe-bash/chunks/{chunk-HHSOUC3Z.js → chunk-HPQE675Q.js} +1 -1
  37. package/dist/safe-bash/chunks/{chunk-BUYRKFW2.js → chunk-I6ECNJMR.js} +1 -1
  38. package/dist/safe-bash/chunks/{pdftk-WRYEP3CA.js → pdftk-Y2TX74LY.js} +2 -1
  39. package/dist/safe-bash/command-chunks/biff-KRHJ63K3-VQPJCVIL.js +5309 -0
  40. package/dist/safe-bash/command-chunks/{chunk-34G2SQX2.js → chunk-2BLTUQNK.js} +2 -2
  41. package/dist/safe-bash/command-chunks/{chunk-LLU2IQEJ.js → chunk-2BNGPR6Z.js} +2 -2
  42. package/dist/safe-bash/command-chunks/{chunk-HWQ2UHMT.js → chunk-2ETEJOYX.js} +18 -18
  43. package/dist/safe-bash/command-chunks/{chunk-NQDIT667.js → chunk-2PKBXGXD.js} +5 -5
  44. package/dist/safe-bash/command-chunks/{chunk-MMBZTYXO.js → chunk-2PQRZDNR.js} +221 -0
  45. package/dist/safe-bash/command-chunks/{chunk-6QBMND4A.js → chunk-2VVJRVYM.js} +1 -1
  46. package/dist/safe-bash/command-chunks/{chunk-G5QVZQCO.js → chunk-3EASXF5D.js} +5 -5
  47. package/dist/safe-bash/command-chunks/{chunk-U3SBHEKH.js → chunk-3EB2FSAN.js} +9 -9
  48. package/dist/safe-bash/command-chunks/{chunk-VB2TUPO2.js → chunk-3EW7GYHM.js} +9 -9
  49. package/dist/safe-bash/command-chunks/{chunk-RNSKXOG3.js → chunk-3GRMU7TM.js} +6 -6
  50. package/dist/safe-bash/command-chunks/chunk-3JM7E42I.js +197 -0
  51. package/dist/safe-bash/command-chunks/{chunk-6L4IYQAT.js → chunk-3MG5EAMX.js} +4 -4
  52. package/dist/safe-bash/command-chunks/{chunk-RASQPOSV.js → chunk-3SPLP2DB.js} +1 -1
  53. package/dist/safe-bash/command-chunks/{chunk-K5COUQAQ.js → chunk-3VGQTLO6.js} +1 -1
  54. package/dist/safe-bash/command-chunks/{chunk-K7CV55K5.js → chunk-3YEQI5B7.js} +10 -10
  55. package/dist/safe-bash/command-chunks/{chunk-ZXR6LXV5.js → chunk-3ZRCL756.js} +48 -4
  56. package/dist/safe-bash/command-chunks/{chunk-SOFM3GPG.js → chunk-42MEXZBJ.js} +1 -1
  57. package/dist/safe-bash/command-chunks/{chunk-GQ2ZSPZ3.js → chunk-46AMTJPE.js} +10 -10
  58. package/dist/safe-bash/command-chunks/{chunk-MTWZEPAR.js → chunk-47IAU25U.js} +2 -2
  59. package/dist/safe-bash/command-chunks/{chunk-6GI3NTCW.js → chunk-4B2ZUGLT.js} +4 -4
  60. package/dist/safe-bash/command-chunks/{chunk-L5MCW6CM.js → chunk-4EHY6J2Z.js} +9 -155
  61. package/dist/safe-bash/command-chunks/{chunk-QQVACHZA.js → chunk-4EZJV4FZ.js} +1 -1
  62. package/dist/safe-bash/command-chunks/{chunk-SSKMPDN4.js → chunk-4GQKCUS5.js} +15 -15
  63. package/dist/safe-bash/command-chunks/{chunk-UOBW5K3M.js → chunk-4RRYWHED.js} +7 -7
  64. package/dist/safe-bash/command-chunks/{chunk-PINR7QET.js → chunk-4UPKVQWH.js} +8 -8
  65. package/dist/safe-bash/command-chunks/{chunk-M7QE2MN7.js → chunk-4YLACJHE.js} +6 -6
  66. package/dist/safe-bash/command-chunks/chunk-5BIQWWLB.js +175 -0
  67. package/dist/safe-bash/command-chunks/{chunk-P3WU3PSL.js → chunk-5L4YGRQU.js} +3 -3
  68. package/dist/safe-bash/command-chunks/{chunk-HKATEVAP.js → chunk-5LFGXN3D.js} +6 -6
  69. package/dist/safe-bash/command-chunks/{chunk-SPLOIABU.js → chunk-5OM3UIK3.js} +3 -3
  70. package/dist/safe-bash/command-chunks/{chunk-TVH4JORU.js → chunk-6LPSKLLD.js} +3 -3
  71. package/dist/safe-bash/command-chunks/{chunk-CV7M2QJU.js → chunk-6QYSF7I2.js} +7 -7
  72. package/dist/safe-bash/command-chunks/{chunk-XVP6V5K3.js → chunk-6VBDJC6V.js} +6 -6
  73. package/dist/safe-bash/command-chunks/{chunk-6N5GHM72.js → chunk-6WNVGCXD.js} +8 -8
  74. package/dist/safe-bash/command-chunks/{chunk-6CCQI6XZ.js → chunk-6XES7Z4G.js} +12 -12
  75. package/dist/safe-bash/command-chunks/{chunk-AFROLW6S.js → chunk-6XGDWFNQ.js} +4 -4
  76. package/dist/safe-bash/command-chunks/{chunk-WTE23QXN.js → chunk-6ZGCKUAM.js} +3 -3
  77. package/dist/safe-bash/command-chunks/chunk-6ZHQB453.js +35 -0
  78. package/dist/safe-bash/command-chunks/{chunk-RIV6XN7K.js → chunk-7DOLY7IV.js} +2 -2
  79. package/dist/safe-bash/command-chunks/{chunk-QD7ZRDUN.js → chunk-7KZ5LWV2.js} +1 -1
  80. package/dist/safe-bash/command-chunks/{chunk-NGR5KOPQ.js → chunk-A347DLRB.js} +3 -3
  81. package/dist/safe-bash/command-chunks/{chunk-ZM2Y4Z3C.js → chunk-A45UG4KT.js} +4 -4
  82. package/dist/safe-bash/command-chunks/{chunk-56NYSX65.js → chunk-ADHFF2IM.js} +9 -9
  83. package/dist/safe-bash/command-chunks/{chunk-ATI464W3.js → chunk-AG2SNMP5.js} +1 -1
  84. package/dist/safe-bash/command-chunks/{chunk-FDCIPJBQ.js → chunk-AM5LANIE.js} +7 -7
  85. package/dist/safe-bash/command-chunks/{chunk-3Q247UDJ.js → chunk-AVGXFWEB.js} +278 -135
  86. package/dist/safe-bash/command-chunks/{chunk-RBTC7OFT.js → chunk-AVOGFREX.js} +5 -5
  87. package/dist/safe-bash/command-chunks/{chunk-QC5RMGSA.js → chunk-AWPI4DZR.js} +3 -3
  88. package/dist/safe-bash/command-chunks/{chunk-FYMNHG7R.js → chunk-AXXZNB7U.js} +13 -13
  89. package/dist/safe-bash/command-chunks/{chunk-Q6S57NOQ.js → chunk-AY3KQ4EN.js} +7 -7
  90. package/dist/safe-bash/command-chunks/{chunk-456PHA3L.js → chunk-BLGGAHQW.js} +1 -1
  91. package/dist/safe-bash/command-chunks/{chunk-CU4DLVME.js → chunk-BLIFGBIO.js} +2 -2
  92. package/dist/safe-bash/command-chunks/{chunk-NARD63DY.js → chunk-BS3ZEQGT.js} +22 -66
  93. package/dist/safe-bash/command-chunks/{chunk-WFVSUXJL.js → chunk-BS5JEUEW.js} +8 -8
  94. package/dist/safe-bash/command-chunks/{chunk-UYWSIIUX.js → chunk-BZMNC7Q5.js} +7 -7
  95. package/dist/safe-bash/command-chunks/{chunk-RHYJVTJO.js → chunk-CCMAHM3I.js} +2 -2
  96. package/dist/safe-bash/command-chunks/{chunk-N4R2SHSS.js → chunk-CCZZVCHX.js} +2 -2
  97. package/dist/safe-bash/command-chunks/{chunk-WGG6G2KG.js → chunk-CIRDVCAZ.js} +7 -7
  98. package/dist/safe-bash/command-chunks/chunk-CK2WFJZN.js +178 -0
  99. package/dist/safe-bash/command-chunks/{chunk-UZL7G57V.js → chunk-CKEMZUE3.js} +7 -7
  100. package/dist/safe-bash/command-chunks/{chunk-B5LDP7AA.js → chunk-CQBACD2V.js} +2 -2
  101. package/dist/safe-bash/command-chunks/{chunk-JYUJAF4L.js → chunk-CSE4VQKG.js} +16 -1
  102. package/dist/safe-bash/command-chunks/{chunk-Q73EMLLZ.js → chunk-CXME4YHU.js} +107 -5
  103. package/dist/safe-bash/command-chunks/{chunk-FTLDRH47.js → chunk-CZ5K2YPU.js} +16 -16
  104. package/dist/safe-bash/command-chunks/{chunk-554Z6IKP.js → chunk-DBLQUZGN.js} +2 -2
  105. package/dist/safe-bash/command-chunks/{chunk-6M6TM5Z5.js → chunk-DBNJEXHK.js} +3 -3
  106. package/dist/safe-bash/command-chunks/{chunk-SPW4GW4Z.js → chunk-DFI7QF3M.js} +2 -2
  107. package/dist/safe-bash/command-chunks/{chunk-ZO5WBWLL.js → chunk-DN6MSXY7.js} +2 -2
  108. package/dist/safe-bash/command-chunks/{chunk-GXLXWZWH.js → chunk-DZH54L3F.js} +3 -3
  109. package/dist/safe-bash/command-chunks/{chunk-XRVKWGVQ.js → chunk-EBHOZIBS.js} +6 -6
  110. package/dist/safe-bash/command-chunks/{chunk-3Y5EME26.js → chunk-ENEIE44W.js} +2 -2
  111. package/dist/safe-bash/command-chunks/{chunk-ATTWQVR2.js → chunk-EQWFKNHJ.js} +17 -17
  112. package/dist/safe-bash/command-chunks/{chunk-YV72XQKL.js → chunk-ETXPMVR6.js} +13 -13
  113. package/dist/safe-bash/command-chunks/{chunk-JFYWVQ4V.js → chunk-EV5G535P.js} +8 -8
  114. package/dist/safe-bash/command-chunks/{chunk-PZMU3Z4L.js → chunk-EVYKV3QI.js} +5 -5
  115. package/dist/safe-bash/command-chunks/{chunk-D6UMSC45.js → chunk-F4YFTO2K.js} +11 -11
  116. package/dist/safe-bash/command-chunks/{chunk-MPUHH2KR.js → chunk-F762XDNG.js} +3 -3
  117. package/dist/safe-bash/command-chunks/{chunk-D2ASPM7R.js → chunk-FF7UGJWS.js} +5 -5
  118. package/dist/safe-bash/command-chunks/{chunk-OA75SGN2.js → chunk-FOONI6BD.js} +7 -7
  119. package/dist/safe-bash/command-chunks/{chunk-DYLNU57U.js → chunk-FSVJ67G5.js} +1 -1
  120. package/dist/safe-bash/command-chunks/{chunk-CLKOGAR3.js → chunk-FSYMSWJU.js} +8 -8
  121. package/dist/safe-bash/command-chunks/{chunk-22MOB45U.js → chunk-FUQMEUAT.js} +6 -6
  122. package/dist/safe-bash/command-chunks/chunk-FWKLBDMK.js +0 -0
  123. package/dist/safe-bash/command-chunks/{chunk-KXPCSVAT.js → chunk-FXCSPPYE.js} +20 -20
  124. package/dist/safe-bash/command-chunks/{chunk-XZ2FWFNV.js → chunk-FYYFV6PW.js} +6 -6
  125. package/dist/safe-bash/command-chunks/{chunk-3OETVNJA.js → chunk-G2COZLXX.js} +9 -9
  126. package/dist/safe-bash/command-chunks/{chunk-ZEX53S5I.js → chunk-G3TAX3CV.js} +7369 -7221
  127. package/dist/safe-bash/command-chunks/{chunk-LXLLA4PM.js → chunk-GCHB7VNX.js} +17 -17
  128. package/dist/safe-bash/command-chunks/{chunk-4Y6O2K35.js → chunk-GLAF45M7.js} +1 -1
  129. package/dist/safe-bash/command-chunks/{chunk-OEJM666F.js → chunk-GQGMQMIM.js} +5 -5
  130. package/dist/safe-bash/command-chunks/{chunk-RRL3Y562.js → chunk-GXMPXMDP.js} +11 -11
  131. package/dist/safe-bash/command-chunks/{chunk-GEM47B2P.js → chunk-GYM5ICK4.js} +7 -7
  132. package/dist/safe-bash/command-chunks/{chunk-A5FZBR7X.js → chunk-H33D4R26.js} +4 -4
  133. package/dist/safe-bash/command-chunks/{chunk-AGLK7OJR.js → chunk-HDSIIQBS.js} +1 -1
  134. package/dist/safe-bash/command-chunks/{chunk-3ZDANXIC.js → chunk-HELAVGZH.js} +3 -3
  135. package/dist/safe-bash/command-chunks/{chunk-S4QH5BXZ.js → chunk-HGIMFVI2.js} +4 -4
  136. package/dist/safe-bash/command-chunks/{chunk-35IPOBWL.js → chunk-HI6ZYH3W.js} +10 -10
  137. package/dist/safe-bash/command-chunks/{chunk-KB7DUBVL.js → chunk-HK6MSB7Z.js} +5 -5
  138. package/dist/safe-bash/command-chunks/{chunk-7ZE3VIAN.js → chunk-IB5QP4LF.js} +2 -2
  139. package/dist/safe-bash/command-chunks/{chunk-UCR5YDV3.js → chunk-IBYMPAUW.js} +1 -1
  140. package/dist/safe-bash/command-chunks/{chunk-LABOWPFB.js → chunk-IHXZMAMY.js} +9 -9
  141. package/dist/safe-bash/command-chunks/{chunk-XPD636C4.js → chunk-IWHNRYER.js} +3 -3
  142. package/dist/safe-bash/command-chunks/{chunk-PPO7YUZF.js → chunk-JGKSWDGP.js} +1 -1
  143. package/dist/safe-bash/command-chunks/{chunk-KCOJA7EM.js → chunk-JR3Q6QNL.js} +7 -7
  144. package/dist/safe-bash/command-chunks/{chunk-S6R3IB36.js → chunk-JUHOL5KB.js} +1 -1
  145. package/dist/safe-bash/command-chunks/{chunk-3O2YEI47.js → chunk-JVKE7YZN.js} +3 -3
  146. package/dist/safe-bash/command-chunks/{chunk-6NATRKUJ.js → chunk-JW6WVNTM.js} +1 -1
  147. package/dist/safe-bash/command-chunks/{chunk-IK6K2HCG.js → chunk-JWORWL72.js} +1 -1
  148. package/dist/safe-bash/command-chunks/{chunk-JOCFI7TG.js → chunk-K2WOMJOQ.js} +1 -1
  149. package/dist/safe-bash/command-chunks/{chunk-XVLWZTPY.js → chunk-K4XNUJVJ.js} +543 -144
  150. package/dist/safe-bash/command-chunks/{chunk-DM2CPMB4.js → chunk-KBAQHE5Y.js} +2 -2
  151. package/dist/safe-bash/command-chunks/chunk-KCLJGRU7.js +737 -0
  152. package/dist/safe-bash/command-chunks/{chunk-TUDFMNPP.js → chunk-KINIV2SV.js} +1 -1
  153. package/dist/safe-bash/command-chunks/{chunk-43TRBJ2N.js → chunk-KPHLESD4.js} +4 -4
  154. package/dist/safe-bash/command-chunks/{chunk-47NEG4UO.js → chunk-KRRG4MGH.js} +222 -46
  155. package/dist/safe-bash/command-chunks/{chunk-33YCKZZX.js → chunk-KSBNZTAZ.js} +6 -6
  156. package/dist/safe-bash/command-chunks/{chunk-4Y34ZG4T.js → chunk-KUOCGGEU.js} +11 -11
  157. package/dist/safe-bash/command-chunks/{chunk-ML5R5JML.js → chunk-KY4LCHUF.js} +1 -1
  158. package/dist/safe-bash/command-chunks/{chunk-2JSDKQ4J.js → chunk-LAPOMHGY.js} +251 -239
  159. package/dist/safe-bash/command-chunks/{chunk-ENT3IV2G.js → chunk-LDW3RF7Y.js} +12 -12
  160. package/dist/safe-bash/command-chunks/{chunk-U27XPNLP.js → chunk-LEO4VRIN.js} +2 -2
  161. package/dist/safe-bash/command-chunks/{chunk-GZ3VIWNN.js → chunk-LKGTH2Q7.js} +7 -7
  162. package/dist/safe-bash/command-chunks/{chunk-ZMHEGDU2.js → chunk-LNTEV56A.js} +2 -2
  163. package/dist/safe-bash/command-chunks/{chunk-DVGXLBUW.js → chunk-LZ2JFMKT.js} +10 -10
  164. package/dist/safe-bash/command-chunks/{chunk-6D2BMAF4.js → chunk-MEM2ZPMI.js} +2 -2
  165. package/dist/safe-bash/command-chunks/{chunk-HTVIYLVB.js → chunk-MGMTRGKM.js} +4 -4
  166. package/dist/safe-bash/command-chunks/{chunk-B3NLITWP.js → chunk-MKK6FM5H.js} +7 -7
  167. package/dist/safe-bash/command-chunks/{chunk-Z2JW6M2D.js → chunk-MKOIPOXX.js} +3 -3
  168. package/dist/safe-bash/command-chunks/chunk-MLOYUXUV.js +244 -0
  169. package/dist/safe-bash/command-chunks/{chunk-CBNKHBLD.js → chunk-MNK3DDH6.js} +2 -2
  170. package/dist/safe-bash/command-chunks/{chunk-JVGUVHWI.js → chunk-MPXMRTMY.js} +10 -10
  171. package/dist/safe-bash/command-chunks/{chunk-TW73OXPR.js → chunk-MVLVIMJ6.js} +6 -6
  172. package/dist/safe-bash/command-chunks/{chunk-TY4WDAHM.js → chunk-MYZ46FQL.js} +1 -1
  173. package/dist/safe-bash/command-chunks/{chunk-TBAIMDGL.js → chunk-N4MUBJCT.js} +1 -1
  174. package/dist/safe-bash/command-chunks/{chunk-NPLVFAD6.js → chunk-N6G3345Q.js} +8 -8
  175. package/dist/safe-bash/command-chunks/{chunk-ZIIO6GRY.js → chunk-NEMUPUUB.js} +7 -7
  176. package/dist/safe-bash/command-chunks/{chunk-K5GB2YMN.js → chunk-NEVQWOU6.js} +10 -10
  177. package/dist/safe-bash/command-chunks/{chunk-FIIAYCWS.js → chunk-NFGCBQN3.js} +2 -2
  178. package/dist/safe-bash/command-chunks/{chunk-PNGDJA6M.js → chunk-NFII726L.js} +2 -2
  179. package/dist/safe-bash/command-chunks/{chunk-JQPNA77Y.js → chunk-NHNZYWPW.js} +2 -2
  180. package/dist/safe-bash/command-chunks/chunk-NQINS4XY.js +156 -0
  181. package/dist/safe-bash/command-chunks/{chunk-APEWTWCC.js → chunk-NRFTYZ2R.js} +6 -6
  182. package/dist/safe-bash/command-chunks/{chunk-THMZLJQD.js → chunk-NYFYTL5G.js} +18 -18
  183. package/dist/safe-bash/command-chunks/{chunk-SMSGLRIH.js → chunk-OTF2AJ5M.js} +6 -6
  184. package/dist/safe-bash/command-chunks/{chunk-QZZ73J2O.js → chunk-OVQP6KH5.js} +6 -6
  185. package/dist/safe-bash/command-chunks/{chunk-HDJVJTCK.js → chunk-P2LT6TGR.js} +9 -9
  186. package/dist/safe-bash/command-chunks/{chunk-YS25EI54.js → chunk-PCCFLPUQ.js} +2 -2
  187. package/dist/safe-bash/command-chunks/{chunk-26VCZHLJ.js → chunk-PIOQBOEK.js} +1 -1
  188. package/dist/safe-bash/command-chunks/{chunk-D2KZ66W4.js → chunk-PIVH35EQ.js} +190 -42
  189. package/dist/safe-bash/command-chunks/{chunk-QYMEASQ6.js → chunk-PLMF35XK.js} +4 -4
  190. package/dist/safe-bash/command-chunks/{chunk-JQVHUSDD.js → chunk-PLR5IULU.js} +5 -5
  191. package/dist/safe-bash/command-chunks/{chunk-2CORNDGF.js → chunk-PS5GDFIP.js} +2 -2
  192. package/dist/safe-bash/command-chunks/{chunk-R6EGGK5M.js → chunk-Q5PWYPQV.js} +7 -7
  193. package/dist/safe-bash/command-chunks/{chunk-COKYZUBW.js → chunk-Q7TVCBU2.js} +1 -1
  194. package/dist/safe-bash/command-chunks/{chunk-EHTOHOTR.js → chunk-QB72X7FF.js} +9 -9
  195. package/dist/safe-bash/command-chunks/{chunk-F3GP3EXE.js → chunk-RGDOYWOD.js} +2 -2
  196. package/dist/safe-bash/command-chunks/{chunk-RQIQ75W5.js → chunk-RHDERFMR.js} +5 -5
  197. package/dist/safe-bash/command-chunks/{chunk-3KMOXEGH.js → chunk-RHU44OMN.js} +2 -2
  198. package/dist/safe-bash/command-chunks/{chunk-7PVHO47B.js → chunk-RIVKF77R.js} +6 -6
  199. package/dist/safe-bash/command-chunks/{chunk-UOR6PXZZ.js → chunk-ROL5AEX6.js} +1 -1
  200. package/dist/safe-bash/command-chunks/{chunk-AHA6IWAJ.js → chunk-RQYPFLZJ.js} +6 -6
  201. package/dist/safe-bash/command-chunks/{chunk-YSMNXMAO.js → chunk-RTNI47C5.js} +4 -4
  202. package/dist/safe-bash/command-chunks/{chunk-W5LLKV5H.js → chunk-RV5AGXOV.js} +2 -2
  203. package/dist/safe-bash/command-chunks/{chunk-PMAM4N33.js → chunk-RXQ2G2YK.js} +9 -9
  204. package/dist/safe-bash/command-chunks/{chunk-EVU7FLDA.js → chunk-S2QNBAN6.js} +7 -7
  205. package/dist/safe-bash/command-chunks/{chunk-YE6OAKK7.js → chunk-S43QRKDC.js} +7 -7
  206. package/dist/safe-bash/command-chunks/{chunk-774GLJAO.js → chunk-S7HIOT7Z.js} +4 -4
  207. package/dist/safe-bash/command-chunks/chunk-SEPUP6TZ.js +63 -0
  208. package/dist/safe-bash/command-chunks/{chunk-JPMYPOYZ.js → chunk-SUTHGUD3.js} +28 -28
  209. package/dist/safe-bash/command-chunks/chunk-SW37YCBW.js +286 -0
  210. package/dist/safe-bash/command-chunks/{chunk-Y4EYCZFT.js → chunk-SWAKALDJ.js} +10 -10
  211. package/dist/safe-bash/command-chunks/{chunk-QUM3SYAJ.js → chunk-SYSX46IV.js} +3 -3
  212. package/dist/safe-bash/command-chunks/{chunk-WGH3RLJY.js → chunk-T5S4SJGO.js} +9 -9
  213. package/dist/safe-bash/command-chunks/{chunk-7JEIWA3A.js → chunk-TID5TSQW.js} +5 -5
  214. package/dist/safe-bash/command-chunks/{chunk-CRV2Q3PB.js → chunk-TJLXSENN.js} +1 -1
  215. package/dist/safe-bash/command-chunks/{chunk-IT7TAC3F.js → chunk-TKCUGMRZ.js} +24 -20
  216. package/dist/safe-bash/command-chunks/{chunk-7GKKMNL6.js → chunk-TXPDKEGY.js} +8 -8
  217. package/dist/safe-bash/command-chunks/{chunk-A2CLZMQZ.js → chunk-UJERQEJB.js} +1 -1
  218. package/dist/safe-bash/command-chunks/{chunk-6VPQ3CDZ.js → chunk-USGZN2KE.js} +5 -5
  219. package/dist/safe-bash/command-chunks/{chunk-LCZDBW55.js → chunk-UYGQEQIP.js} +5 -5
  220. package/dist/safe-bash/command-chunks/{chunk-MPORWUTU.js → chunk-V5XC43BX.js} +8 -8
  221. package/dist/safe-bash/command-chunks/{chunk-AIMSZBWP.js → chunk-V7E3PZOK.js} +9 -9
  222. package/dist/safe-bash/command-chunks/{chunk-CNHRVUHA.js → chunk-VDTFVRYX.js} +1 -1
  223. package/dist/safe-bash/command-chunks/{chunk-KJ4XXZIL.js → chunk-VT2PHQ63.js} +582 -59
  224. package/dist/safe-bash/command-chunks/{chunk-MOZD7RUY.js → chunk-VT7UBPAE.js} +38 -15
  225. package/dist/safe-bash/command-chunks/{chunk-QDVI2YB6.js → chunk-VUWXLH3E.js} +2 -2
  226. package/dist/safe-bash/command-chunks/{chunk-X7FA7ZD5.js → chunk-W3ZSWK76.js} +8 -8
  227. package/dist/safe-bash/command-chunks/{chunk-JPA2PUYI.js → chunk-WBKB7HBZ.js} +8 -8
  228. package/dist/safe-bash/command-chunks/{chunk-MIRL7HTF.js → chunk-WJ2ERUCQ.js} +1 -1
  229. package/dist/safe-bash/command-chunks/{chunk-36XGIPOG.js → chunk-WTVJLHMG.js} +1 -1
  230. package/dist/safe-bash/command-chunks/{chunk-SLQWQKXP.js → chunk-WWHMI4S3.js} +9 -9
  231. package/dist/safe-bash/command-chunks/{chunk-2UBZALAK.js → chunk-WYZG3DRR.js} +1 -1
  232. package/dist/safe-bash/command-chunks/{chunk-YORJDX4V.js → chunk-WZRFS5OY.js} +4 -4
  233. package/dist/safe-bash/command-chunks/{chunk-EHSM5ZQS.js → chunk-X6OHFKBL.js} +8 -8
  234. package/dist/safe-bash/command-chunks/{chunk-S6ZTBXYO.js → chunk-XKAUKLF7.js} +13 -13
  235. package/dist/safe-bash/command-chunks/{chunk-EUT24Y5Z.js → chunk-XM5QJCPD.js} +8 -8
  236. package/dist/safe-bash/command-chunks/{chunk-WXRYDALR.js → chunk-XMTR7QGL.js} +4 -4
  237. package/dist/safe-bash/command-chunks/{chunk-4CKFNXRN.js → chunk-XNGM3W5R.js} +1 -1
  238. package/dist/safe-bash/command-chunks/{chunk-2ZFLMWOX.js → chunk-XTEIT5CI.js} +1 -1
  239. package/dist/safe-bash/command-chunks/{chunk-4DLIUTQV.js → chunk-XU6S3XUZ.js} +11 -11
  240. package/dist/safe-bash/command-chunks/{chunk-CJQSAATC.js → chunk-XUJAQA3S.js} +30 -30
  241. package/dist/safe-bash/command-chunks/{chunk-W5YSINXC.js → chunk-Y42KSX63.js} +6 -6
  242. package/dist/safe-bash/command-chunks/{chunk-UAXSE3XE.js → chunk-Y54L4P4J.js} +5 -5
  243. package/dist/safe-bash/command-chunks/{chunk-6WQD7LRA.js → chunk-YAD7EV4N.js} +14 -14
  244. package/dist/safe-bash/command-chunks/{chunk-WVMHRNXZ.js → chunk-YRPXBGRX.js} +3 -3
  245. package/dist/safe-bash/command-chunks/{chunk-5HPU7D36.js → chunk-Z2WNYEPD.js} +4 -4
  246. package/dist/safe-bash/command-chunks/{chunk-SDTPO2VV.js → chunk-Z7QOSXQC.js} +7 -7
  247. package/dist/safe-bash/command-chunks/{chunk-WJCN2IXI.js → chunk-ZQM37BGE.js} +2 -2
  248. package/dist/safe-bash/command-chunks/{chunk-W3HV45CI.js → chunk-ZSQZHFWS.js} +9 -9
  249. package/dist/safe-bash/command-chunks/{chunk-IDJQP3A6.js → chunk-ZTMZO4IT.js} +1 -1
  250. package/dist/safe-bash/command-chunks/{chunk-RID6VYS3.js → chunk-ZU2KJMXO.js} +8 -8
  251. package/dist/safe-bash/command-chunks/{chunk-YXKNJ6EM.js → chunk-ZXELXF2H.js} +5 -5
  252. package/dist/safe-bash/command-chunks/{clipboard-BBDK33GP-VB22F7GI.js → clipboard-BBDK33GP-QZ4ERNQX.js} +2 -2
  253. package/dist/safe-bash/command-chunks/{command-engine-BCUQGJJ4.js → command-engine-7V6PZR7G.js} +1012 -678
  254. package/dist/safe-bash/command-chunks/{engine-LAUEWYSQ-DQCEI5HE.js → engine-UYJENSWK-VSCGKSQV.js} +1 -1
  255. package/dist/safe-bash/command-chunks/{gnumeric-UJPXWBVR-YPXTNEDZ.js → gnumeric-UJPXWBVR-7VOHQAPM.js} +2 -2
  256. package/dist/safe-bash/command-chunks/{model-store-E7BHBFJC.js → model-store-UB5DWMAP.js} +24 -24
  257. package/dist/safe-bash/command-chunks/paradox-4FCZE53D-LQPGVMEL.js +365 -0
  258. package/dist/safe-bash/commands/pandoc/index.browser.js +1 -1
  259. package/dist/safe-bash/full-core.browser.js +2 -2
  260. package/dist/safe-bash/plugins/index.browser.js +2 -2
  261. package/dist/safe-bash-command-awk/awk-runtime.js +3 -3
  262. package/dist/safe-bash-command-awk/awk.js +4 -4
  263. package/dist/safe-bash-command-awk/index.js +4 -4
  264. package/dist/safe-bash-command-diff/diff.js +2 -2
  265. package/dist/safe-bash-command-diff/index.js +3 -3
  266. package/dist/safe-bash-command-diff/sync.js +2 -2
  267. package/dist/safe-bash-command-du/du.js +2 -2
  268. package/dist/safe-bash-command-du/index.js +2 -2
  269. package/dist/safe-bash-command-ffmpeg/index.js +1 -1
  270. package/dist/safe-bash-command-ffprobe/index.js +2 -2
  271. package/dist/safe-bash-command-ffprobe/media.d.ts +3 -1
  272. package/dist/safe-bash-command-ffprobe/media.js +2 -2
  273. package/dist/safe-bash-command-html-to-markdown/budget.js +2 -1
  274. package/dist/safe-bash-command-html-to-markdown/entities.js +4 -3
  275. package/dist/safe-bash-command-html-to-markdown/index.js +533 -310
  276. package/dist/safe-bash-command-html-to-markdown/input.js +6 -5
  277. package/dist/safe-bash-command-html-to-markdown/options.js +2 -1
  278. package/dist/safe-bash-command-html-to-markdown/parser.js +5 -4
  279. package/dist/safe-bash-command-html-to-markdown/render.js +6 -5
  280. package/dist/safe-bash-command-html-to-markdown/stored-text.d.ts +50 -0
  281. package/dist/safe-bash-command-html-to-markdown/stored-text.js +12 -0
  282. package/dist/safe-bash-command-html-to-markdown/text.js +3 -2
  283. package/dist/safe-bash-command-htmlq/contracts.d.ts +5 -0
  284. package/dist/safe-bash-command-htmlq/index.js +2006 -259
  285. package/dist/safe-bash-command-htmlq/selectors.d.ts +38 -1
  286. package/dist/safe-bash-command-htmlq/serializer.d.ts +1 -0
  287. package/dist/safe-bash-command-htmlq/tree.d.ts +4 -2
  288. package/dist/safe-bash-command-iconv/command.js +2 -2
  289. package/dist/safe-bash-command-iconv/index.js +2 -2
  290. package/dist/safe-bash-command-llm/command.js +3 -3
  291. package/dist/safe-bash-command-llm/index.js +9 -9
  292. package/dist/safe-bash-command-llm/openai.js +2 -2
  293. package/dist/safe-bash-command-llm/providers/index.js +2 -2
  294. package/dist/safe-bash-command-llm/providers/openai.js +2 -2
  295. package/dist/safe-bash-command-node/commands/node/browser.js +2 -2
  296. package/dist/safe-bash-command-node/commands/node/default-runtime.js +2 -2
  297. package/dist/safe-bash-command-node/commands/node/safejs.js +2 -2
  298. package/dist/safe-bash-command-pandoc/command.js +7 -7
  299. package/dist/safe-bash-command-pandoc/index.js +46 -46
  300. package/dist/safe-bash-command-patch/index.js +6 -6
  301. package/dist/safe-bash-command-patch/patch-envelope.js +53 -3
  302. package/dist/safe-bash-command-patch/patch-formats.d.ts +7 -2
  303. package/dist/safe-bash-command-patch/patch-formats.js +6 -4
  304. package/dist/safe-bash-command-patch/patch-gnu-paths.d.ts +7 -7
  305. package/dist/safe-bash-command-patch/patch-gnu-reject.d.ts +3 -2
  306. package/dist/safe-bash-command-patch/patch-gnu-reject.js +4 -3
  307. package/dist/safe-bash-command-patch/patch-publication.js +2 -1
  308. package/dist/safe-bash-command-patch/patch.js +6 -6
  309. package/dist/safe-bash-command-patch/stored-patch.d.ts +26 -0
  310. package/dist/safe-bash-command-patch/stored-target.d.ts +40 -0
  311. package/dist/safe-bash-command-patch/unified.d.ts +23 -10
  312. package/dist/safe-bash-command-patch/unified.js +3 -1
  313. package/dist/safe-bash-command-pdftk/index.d.ts +6 -2
  314. package/dist/safe-bash-command-pdftk/index.js +1247 -373
  315. package/dist/safe-bash-command-playwright-cli/index.js +26 -26
  316. package/dist/safe-bash-command-playwright-cli/playwright/abilities.js +10 -10
  317. package/dist/safe-bash-command-playwright-cli/playwright/controller.js +14 -14
  318. package/dist/safe-bash-command-playwright-cli/playwright/index.js +23 -23
  319. package/dist/safe-bash-command-playwright-cli/playwright/snapshot.js +2 -2
  320. package/dist/safe-bash-command-playwright-cli/playwright/standard-capabilities.js +6 -6
  321. package/dist/safe-bash-command-playwright-cli/playwright/storage-capabilities.js +4 -4
  322. package/dist/safe-bash-command-pptx/command-engine.d.ts +5 -1
  323. package/dist/safe-bash-command-pptx/engine.js +1 -1
  324. package/dist/safe-bash-command-pptx/index.d.ts +1 -1
  325. package/dist/safe-bash-command-pptx/index.js +172 -19
  326. package/dist/safe-bash-command-pptx/streaming-inputs.d.ts +7 -2
  327. package/dist/safe-bash-command-python/executor.js +5 -5
  328. package/dist/safe-bash-command-python/index.js +5 -5
  329. package/dist/safe-bash-command-python/jspi.js +2 -2
  330. package/dist/safe-bash-command-soffice/index.js +1 -1
  331. package/dist/safe-bash-command-sort/index.js +3 -3
  332. package/dist/safe-bash-command-ssconvert/index.js +2 -2
  333. package/dist/safe-bash-command-tar/create.js +2 -2
  334. package/dist/safe-bash-command-tar/extract.js +2 -2
  335. package/dist/safe-bash-command-tar/index.js +8 -8
  336. package/dist/safe-bash-command-tar/modes.js +4 -4
  337. package/dist/safe-bash-command-timeout/index.js +3 -3
  338. package/dist/safe-bash-command-tree/index.js +2 -2
  339. package/dist/safe-bash-command-tree/tree.js +2 -2
  340. package/dist/safe-bash-command-xmllint/index.js +22 -31
  341. package/dist/safe-bash-command-xz/index.js +5 -5
  342. package/dist/safe-bash-compression-engine/files.js +2 -2
  343. package/dist/safe-bash-compression-engine/operand.js +4 -4
  344. package/dist/safe-bash-contracts/diagnostics.js +3 -3
  345. package/dist/safe-bash-contracts/escaping.js +10 -10
  346. package/dist/safe-bash-contracts/filesystem-descriptor.js +1 -1
  347. package/dist/safe-bash-contracts/filesystem-output.js +6 -6
  348. package/dist/safe-bash-contracts/index.js +33 -33
  349. package/dist/safe-bash-contracts/io.js +2 -2
  350. package/dist/safe-bash-contracts/output.js +3 -3
  351. package/dist/safe-bash-docx-engine/ancillary-resources.js +5 -5
  352. package/dist/safe-bash-docx-engine/batch-operations.js +63 -63
  353. package/dist/safe-bash-docx-engine/batch-result-schema.js +74 -74
  354. package/dist/safe-bash-docx-engine/batch.js +74 -74
  355. package/dist/safe-bash-docx-engine/bookmarks.js +13 -13
  356. package/dist/safe-bash-docx-engine/charts.js +6 -6
  357. package/dist/safe-bash-docx-engine/command-option-rules.js +3 -3
  358. package/dist/safe-bash-docx-engine/comments.js +21 -21
  359. package/dist/safe-bash-docx-engine/control-bindings.js +16 -16
  360. package/dist/safe-bash-docx-engine/control-repeat.js +16 -16
  361. package/dist/safe-bash-docx-engine/controls.js +14 -14
  362. package/dist/safe-bash-docx-engine/create.js +8 -8
  363. package/dist/safe-bash-docx-engine/diagrams.js +6 -6
  364. package/dist/safe-bash-docx-engine/diff.js +8 -8
  365. package/dist/safe-bash-docx-engine/document-properties.js +12 -12
  366. package/dist/safe-bash-docx-engine/equations.js +12 -12
  367. package/dist/safe-bash-docx-engine/extract.js +9 -9
  368. package/dist/safe-bash-docx-engine/fields.js +18 -18
  369. package/dist/safe-bash-docx-engine/font-inventory.js +13 -13
  370. package/dist/safe-bash-docx-engine/font-resources.js +3 -3
  371. package/dist/safe-bash-docx-engine/image-batch-operations.js +11 -11
  372. package/dist/safe-bash-docx-engine/image-insertion.js +17 -17
  373. package/dist/safe-bash-docx-engine/image-layout.js +14 -14
  374. package/dist/safe-bash-docx-engine/image-replacement.js +19 -19
  375. package/dist/safe-bash-docx-engine/images.js +14 -14
  376. package/dist/safe-bash-docx-engine/index.js +102 -102
  377. package/dist/safe-bash-docx-engine/inspection.js +15 -15
  378. package/dist/safe-bash-docx-engine/invocation.js +4 -4
  379. package/dist/safe-bash-docx-engine/io.js +6 -6
  380. package/dist/safe-bash-docx-engine/links.js +17 -17
  381. package/dist/safe-bash-docx-engine/lists.js +16 -16
  382. package/dist/safe-bash-docx-engine/locations.js +10 -10
  383. package/dist/safe-bash-docx-engine/notes.js +18 -18
  384. package/dist/safe-bash-docx-engine/objects.js +14 -14
  385. package/dist/safe-bash-docx-engine/pack.js +9 -9
  386. package/dist/safe-bash-docx-engine/package-view-batch-operations.js +19 -19
  387. package/dist/safe-bash-docx-engine/pandoc-adapter.js +25 -25
  388. package/dist/safe-bash-docx-engine/paragraph-edit.js +21 -21
  389. package/dist/safe-bash-docx-engine/publication.js +6 -6
  390. package/dist/safe-bash-docx-engine/removal.js +16 -16
  391. package/dist/safe-bash-docx-engine/revision-decisions.js +16 -16
  392. package/dist/safe-bash-docx-engine/revision-edit.js +15 -15
  393. package/dist/safe-bash-docx-engine/revisions.js +12 -12
  394. package/dist/safe-bash-docx-engine/run-format.js +15 -15
  395. package/dist/safe-bash-docx-engine/sanitize.js +29 -29
  396. package/dist/safe-bash-docx-engine/sections.js +15 -15
  397. package/dist/safe-bash-docx-engine/settings.js +6 -6
  398. package/dist/safe-bash-docx-engine/shape-edit.js +16 -16
  399. package/dist/safe-bash-docx-engine/signatures.js +11 -11
  400. package/dist/safe-bash-docx-engine/stories.js +18 -18
  401. package/dist/safe-bash-docx-engine/structure-model-batch-operations.js +34 -34
  402. package/dist/safe-bash-docx-engine/style-model-batch-operations.js +24 -24
  403. package/dist/safe-bash-docx-engine/style-model-result-schema.js +39 -39
  404. package/dist/safe-bash-docx-engine/styles.js +14 -14
  405. package/dist/safe-bash-docx-engine/table-edit.js +23 -23
  406. package/dist/safe-bash-docx-engine/table-read.js +11 -11
  407. package/dist/safe-bash-docx-engine/template.js +17 -17
  408. package/dist/safe-bash-docx-engine/text-replace.js +15 -15
  409. package/dist/safe-bash-docx-engine/text-resource-read.js +11 -11
  410. package/dist/safe-bash-docx-engine/text.js +11 -11
  411. package/dist/safe-bash-docx-engine/validation.js +4 -4
  412. package/dist/safe-bash-docx-engine/xml-parts.js +17 -17
  413. package/dist/safe-bash-io-engine/commands/text-programs/shared.js +4 -4
  414. package/dist/safe-bash-line-ending-engine/command.js +3 -3
  415. package/dist/safe-bash-line-ending-engine/convert.js +2 -2
  416. package/dist/safe-bash-line-ending-engine/index.js +6 -6
  417. package/dist/safe-bash-line-ending-engine/info.js +2 -2
  418. package/dist/safe-bash-markdown-engine/commonmark-blocks.js +4 -4
  419. package/dist/safe-bash-markdown-engine/commonmark-inlines.js +4 -4
  420. package/dist/safe-bash-markdown-engine/commonmark-syntax.js +2 -2
  421. package/dist/safe-bash-markdown-engine/gfm-syntax.js +3 -3
  422. package/dist/safe-bash-markdown-engine/index.js +5 -5
  423. package/dist/safe-bash-network-engine/transfer.js +3 -3
  424. package/dist/safe-bash-presentation-engine/accessibility.js +31 -30
  425. package/dist/safe-bash-presentation-engine/animation-editing.js +16 -15
  426. package/dist/safe-bash-presentation-engine/animations.js +16 -15
  427. package/dist/safe-bash-presentation-engine/backgrounds.js +17 -16
  428. package/dist/safe-bash-presentation-engine/bytes.js +3 -3
  429. package/dist/safe-bash-presentation-engine/chart-editing.js +34 -33
  430. package/dist/safe-bash-presentation-engine/chart-object-operations.js +25 -24
  431. package/dist/safe-bash-presentation-engine/charts.js +31 -30
  432. package/dist/safe-bash-presentation-engine/command-placeholder.js +59 -56
  433. package/dist/safe-bash-presentation-engine/comments.js +17 -16
  434. package/dist/safe-bash-presentation-engine/connector-operations.js +32 -31
  435. package/dist/safe-bash-presentation-engine/connectors.js +29 -28
  436. package/dist/safe-bash-presentation-engine/content-types.js +4 -4
  437. package/dist/safe-bash-presentation-engine/creation.js +6 -6
  438. package/dist/safe-bash-presentation-engine/diff.js +32 -31
  439. package/dist/safe-bash-presentation-engine/drawing-enums.d.ts +10 -10
  440. package/dist/safe-bash-presentation-engine/drawing-format.js +20 -19
  441. package/dist/safe-bash-presentation-engine/drawing-operations.js +31 -30
  442. package/dist/safe-bash-presentation-engine/drawing-schema.js +21 -20
  443. package/dist/safe-bash-presentation-engine/equations.js +17 -16
  444. package/dist/safe-bash-presentation-engine/errors.js +2 -2
  445. package/dist/safe-bash-presentation-engine/fields.js +17 -16
  446. package/dist/safe-bash-presentation-engine/font-metrics.js +3 -3
  447. package/dist/safe-bash-presentation-engine/image-extraction.js +20 -19
  448. package/dist/safe-bash-presentation-engine/image-formatting.js +32 -31
  449. package/dist/safe-bash-presentation-engine/image-insertion.js +18 -17
  450. package/dist/safe-bash-presentation-engine/image-replacement.js +21 -20
  451. package/dist/safe-bash-presentation-engine/image-value.js +4 -4
  452. package/dist/safe-bash-presentation-engine/images.js +19 -18
  453. package/dist/safe-bash-presentation-engine/index.d.ts +5 -1
  454. package/dist/safe-bash-presentation-engine/index.js +121 -108
  455. package/dist/safe-bash-presentation-engine/layouts.js +16 -15
  456. package/dist/safe-bash-presentation-engine/length.js +3 -3
  457. package/dist/safe-bash-presentation-engine/links.js +16 -15
  458. package/dist/safe-bash-presentation-engine/masters.js +15 -14
  459. package/dist/safe-bash-presentation-engine/media-editing.js +24 -23
  460. package/dist/safe-bash-presentation-engine/media-extraction.js +17 -16
  461. package/dist/safe-bash-presentation-engine/media.js +16 -15
  462. package/dist/safe-bash-presentation-engine/memberships.js +15 -14
  463. package/dist/safe-bash-presentation-engine/notes.js +16 -15
  464. package/dist/safe-bash-presentation-engine/ole-enum.js +4 -4
  465. package/dist/safe-bash-presentation-engine/ole-insertion.js +20 -19
  466. package/dist/safe-bash-presentation-engine/opaque-objects.js +9 -9
  467. package/dist/safe-bash-presentation-engine/package-reader.js +5 -5
  468. package/dist/safe-bash-presentation-engine/package-tools.d.ts +3 -0
  469. package/dist/safe-bash-presentation-engine/package-tools.js +27 -17
  470. package/dist/safe-bash-presentation-engine/package-uri.js +3 -3
  471. package/dist/safe-bash-presentation-engine/package-writer.js +4 -4
  472. package/dist/safe-bash-presentation-engine/presentation-model.js +58 -55
  473. package/dist/safe-bash-presentation-engine/presentation-settings.js +14 -13
  474. package/dist/safe-bash-presentation-engine/properties.js +16 -15
  475. package/dist/safe-bash-presentation-engine/relationships.js +4 -4
  476. package/dist/safe-bash-presentation-engine/resource-limits.js +1 -1
  477. package/dist/safe-bash-presentation-engine/retained-archive-staging.d.ts +19 -0
  478. package/dist/safe-bash-presentation-engine/retained-extraction-output.d.ts +18 -0
  479. package/dist/safe-bash-presentation-engine/retained-frame-formatting.d.ts +14 -0
  480. package/dist/safe-bash-presentation-engine/retained-inspection.js +14 -12
  481. package/dist/safe-bash-presentation-engine/retained-package-extraction.d.ts +22 -0
  482. package/dist/safe-bash-presentation-engine/retained-package-packing.d.ts +19 -0
  483. package/dist/safe-bash-presentation-engine/retained-package.d.ts +2 -0
  484. package/dist/safe-bash-presentation-engine/retained-package.js +6 -4
  485. package/dist/safe-bash-presentation-engine/retained-text.d.ts +9 -2
  486. package/dist/safe-bash-presentation-engine/retained-text.js +131 -30
  487. package/dist/safe-bash-presentation-engine/retained-xml-document.d.ts +1 -0
  488. package/dist/safe-bash-presentation-engine/retained-xml-parts.d.ts +5 -1
  489. package/dist/safe-bash-presentation-engine/retained-xml-publication.d.ts +18 -0
  490. package/dist/safe-bash-presentation-engine/retained-xml-replacement.d.ts +13 -0
  491. package/dist/safe-bash-presentation-engine/sanitize.js +17 -16
  492. package/dist/safe-bash-presentation-engine/selectors.js +10 -10
  493. package/dist/safe-bash-presentation-engine/shape-groups.js +31 -30
  494. package/dist/safe-bash-presentation-engine/shape-operations.js +30 -29
  495. package/dist/safe-bash-presentation-engine/shape-path-operations.js +32 -31
  496. package/dist/safe-bash-presentation-engine/shape-paths.js +16 -15
  497. package/dist/safe-bash-presentation-engine/shape-presets.js +3 -3
  498. package/dist/safe-bash-presentation-engine/shape-selection.js +31 -30
  499. package/dist/safe-bash-presentation-engine/shape-transforms.js +18 -17
  500. package/dist/safe-bash-presentation-engine/shapes.d.ts +1 -1
  501. package/dist/safe-bash-presentation-engine/shapes.js +27 -26
  502. package/dist/safe-bash-presentation-engine/slide-copy.js +17 -16
  503. package/dist/safe-bash-presentation-engine/slide-import.js +18 -17
  504. package/dist/safe-bash-presentation-engine/slide-merge-split.js +20 -19
  505. package/dist/safe-bash-presentation-engine/slide-model.js +43 -42
  506. package/dist/safe-bash-presentation-engine/slide-removal.js +18 -17
  507. package/dist/safe-bash-presentation-engine/slide-transfer-budget.js +9 -9
  508. package/dist/safe-bash-presentation-engine/slides.js +19 -16
  509. package/dist/safe-bash-presentation-engine/table-operations.js +33 -32
  510. package/dist/safe-bash-presentation-engine/table-spans.js +32 -31
  511. package/dist/safe-bash-presentation-engine/tables.js +31 -30
  512. package/dist/safe-bash-presentation-engine/tags.js +16 -15
  513. package/dist/safe-bash-presentation-engine/template-bindings.js +33 -32
  514. package/dist/safe-bash-presentation-engine/template-repeat.js +40 -39
  515. package/dist/safe-bash-presentation-engine/text-fitting.js +27 -26
  516. package/dist/safe-bash-presentation-engine/text-frames.d.ts +13 -0
  517. package/dist/safe-bash-presentation-engine/text-frames.js +29 -26
  518. package/dist/safe-bash-presentation-engine/text-paragraphs.js +27 -26
  519. package/dist/safe-bash-presentation-engine/text-reading.js +11 -11
  520. package/dist/safe-bash-presentation-engine/text-replacement.js +17 -16
  521. package/dist/safe-bash-presentation-engine/text-runs.js +20 -19
  522. package/dist/safe-bash-presentation-engine/themes.js +16 -15
  523. package/dist/safe-bash-presentation-engine/transitions.js +16 -15
  524. package/dist/safe-bash-presentation-engine/validation.js +10 -9
  525. package/dist/safe-bash-presentation-engine/xml-parts.d.ts +2 -0
  526. package/dist/safe-bash-presentation-engine/xml-parts.js +23 -15
  527. package/dist/safe-bash-presentation-engine/xml-view.js +3 -3
  528. package/dist/safe-bash-presentation-engine/xml.js +3 -3
  529. package/dist/safe-bash-query-engine/index.js +4 -4
  530. package/dist/safe-bash-query-engine/interpreter.js +2 -2
  531. package/dist/safe-bash-query-engine/query-core.js +4 -4
  532. package/dist/safe-bash-regex-engine/index.js +1 -1
  533. package/dist/safe-bash-regex-engine/python-glob.js +1 -1
  534. package/dist/safe-bash-regex-engine/text/regex.d.ts +19 -0
  535. package/dist/safe-bash-regex-engine/text/regex.js +1 -1
  536. package/dist/safe-bash-xml-engine/document.js +3 -3
  537. package/dist/safe-bash-xml-engine/evaluate.js +1 -1
  538. package/dist/safe-bash-xml-engine/index.d.ts +1 -0
  539. package/dist/safe-bash-xml-engine/index.js +9 -5
  540. package/dist/safe-bash-xml-engine/query.js +2 -2
  541. package/dist/safe-bash-xml-engine/recovery.d.ts +10 -0
  542. package/dist/safe-bash-xml-engine/stored-document.d.ts +3 -3
  543. package/dist/safe-bash-xml-engine/stored-document.js +1 -1
  544. package/dist/safe-bash-xml-engine/stored-evaluate.js +1 -1
  545. package/dist/safe-bash-zip-engine/zip/repair.js +3 -3
  546. package/dist/safe-bash-zip-engine/zip/volumes.js +3 -3
  547. package/dist/spreadsheet-engine/datasource.js +16 -2
  548. package/dist/spreadsheet-engine/formulas/diagnostics.d.ts +2 -1
  549. package/dist/spreadsheet-engine/formulas/diagnostics.js +2 -2
  550. package/dist/spreadsheet-engine/formulas/evaluator.d.ts +1 -1
  551. package/dist/spreadsheet-engine/formulas/evaluator.js +2 -1
  552. package/dist/spreadsheet-engine/formulas/functions/python-printf.js +56 -33
  553. package/dist/spreadsheet-format-xls/biff-encrypted-properties.d.ts +1 -1
  554. package/dist/spreadsheet-format-xls/biff-encrypted-properties.js +54 -24
  555. package/dist/spreadsheet-format-xls/biff-properties-merge.d.ts +6 -2
  556. package/dist/spreadsheet-format-xls/biff-properties-merge.js +413 -296
  557. package/dist/spreadsheet-format-xls/biff-properties-write.js +40 -23
  558. package/dist/spreadsheet-format-xls/biff-properties.js +95 -175
  559. package/dist/spreadsheet-format-xls/biff-property-dictionary.d.ts +5 -0
  560. package/dist/spreadsheet-format-xls/biff-property-dictionary.js +75 -0
  561. package/dist/spreadsheet-format-xls/biff-property-index.d.ts +23 -0
  562. package/dist/spreadsheet-format-xls/biff-property-index.js +93 -0
  563. package/dist/spreadsheet-format-xls/biff-property-name.d.ts +4 -0
  564. package/dist/spreadsheet-format-xls/biff-property-name.js +114 -0
  565. package/dist/spreadsheet-format-xls/biff-property-range.d.ts +17 -3
  566. package/dist/spreadsheet-format-xls/biff-property-range.js +178 -37
  567. package/dist/spreadsheet-format-xls/biff-property-text.d.ts +6 -0
  568. package/dist/spreadsheet-format-xls/biff-property-text.js +68 -0
  569. package/dist/spreadsheet-format-xls/biff-property-transcode.d.ts +5 -0
  570. package/dist/spreadsheet-format-xls/biff-property-transcode.js +45 -0
  571. package/package.json +8 -3
  572. package/dist/safe-bash/command-chunks/biff-YKPDH35C-MVQIWNKV.js +0 -4974
  573. package/dist/safe-bash/command-chunks/chunk-2VLAXKTS.js +0 -245
  574. package/dist/safe-bash/command-chunks/chunk-5Q22ZLNC.js +0 -127
  575. package/dist/safe-bash/command-chunks/chunk-JKLOBSMP.js +0 -56
  576. package/dist/safe-bash/command-chunks/chunk-JYTESTBS.js +0 -99
  577. package/dist/safe-bash/command-chunks/chunk-ZEGNRZV2.js +0 -333
  578. package/dist/safe-bash/command-chunks/paradox-ZWWXYY4J-JYOSWSBL.js +0 -362
  579. package/dist/spreadsheet-format-xls/biff-properties-layout.js +0 -56
  580. package/dist/safe-bash/command-chunks/{chunk-X2HVVMTW.js → chunk-AW4Q3GZW.js} +6 -6
  581. package/dist/safe-bash/command-chunks/{chunk-JC2EV66U.js → chunk-BJXADHRT.js} +3 -3
  582. package/dist/safe-bash/command-chunks/{chunk-XI2LETBJ.js → chunk-BXU5Y7I5.js} +3 -3
  583. package/dist/safe-bash/command-chunks/{chunk-PVLPWVRH.js → chunk-D3HW7R2N.js} +3 -3
  584. package/dist/safe-bash/command-chunks/{chunk-OLK3DCJD.js → chunk-DYERIXPU.js} +3 -3
  585. package/dist/safe-bash/command-chunks/{chunk-WYBCSJFG.js → chunk-FWCUEZ3K.js} +3 -3
  586. package/dist/safe-bash/command-chunks/{chunk-FF2SQ2GP.js → chunk-GGH376XQ.js} +3 -3
  587. package/dist/safe-bash/command-chunks/{chunk-D66Q7QJ3.js → chunk-JRSZ5IGD.js} +6 -6
  588. package/dist/safe-bash/command-chunks/{chunk-Z3YB4EVE.js → chunk-KSM5CCHT.js} +8 -8
  589. package/dist/safe-bash/command-chunks/{chunk-NJ4NTTCR.js → chunk-LNLACEAN.js} +8 -8
  590. package/dist/safe-bash/command-chunks/{chunk-NBTG6NF6.js → chunk-LTJRUMK6.js} +3 -3
  591. package/dist/safe-bash/command-chunks/{chunk-XCYTG7CR.js → chunk-NJGL5JQ6.js} +3 -3
  592. package/dist/safe-bash/command-chunks/{chunk-SZ66JC25.js → chunk-Q7J2NTH2.js} +3 -3
  593. package/dist/safe-bash/command-chunks/{chunk-MDV7W5AS.js → chunk-SKNI2XQA.js} +3 -3
  594. package/dist/safe-bash/command-chunks/{chunk-7ZWACKCG.js → chunk-T6OXG7QQ.js} +3 -3
  595. package/dist/safe-bash/command-chunks/{chunk-ECDEPKKW.js → chunk-W25EIKDJ.js} +3 -3
  596. package/dist/safe-bash/command-chunks/{chunk-4YSBUQPV.js → chunk-W2FKFEVY.js} +3 -3
  597. package/dist/safe-bash/command-chunks/{chunk-2CIDPOUV.js → chunk-WSNHJZQ5.js} +3 -3
  598. package/dist/safe-bash/command-chunks/{chunk-4H3TYOVC.js → chunk-Y7AXMCFV.js} +3 -3
  599. package/dist/safe-bash/command-chunks/{chunk-U6IEK2CI.js → chunk-YPG55QTP.js} +7 -7
  600. package/dist/safe-bash/command-chunks/{chunk-252L5YC5.js → chunk-Z37OM247.js} +6 -6
  601. package/dist/safe-bash/command-chunks/{pln-DFS7VLVS-JATX6FS7.js → pln-DFS7VLVS-OVOBS4QX.js} +3 -3
  602. package/dist/safe-bash/command-chunks/{psion-YBI6JEQI-6OMC2PGC.js → psion-YBI6JEQI-GY4S6ZLC.js} +3 -3
@@ -26870,6 +26870,7 @@ function cosStream(dataOrDict, optionsOrData = {}, span) {
26870
26870
  };
26871
26871
  }
26872
26872
  function dictGet(dict, key) {
26873
+ if (dict.storedEntries) throw new TypeError("Stored dictionary requires asynchronous access");
26873
26874
  for (let i = dict.entries.length - 1; i >= 0; i--) {
26874
26875
  if (dict.entries[i].key.decoded === key) {
26875
26876
  return dict.entries[i].value;
@@ -26878,6 +26879,7 @@ function dictGet(dict, key) {
26878
26879
  return void 0;
26879
26880
  }
26880
26881
  function dictSet(dict, key, value) {
26882
+ if (dict.storedEntries) throw new TypeError("Stored dictionary requires asynchronous access");
26881
26883
  for (let i = dict.entries.length - 1; i >= 0; i--) {
26882
26884
  if (dict.entries[i].key.decoded === key) {
26883
26885
  dict.entries[i] = { key: cosName(key), value };
@@ -26887,6 +26889,7 @@ function dictSet(dict, key, value) {
26887
26889
  dict.entries.push({ key: cosName(key), value });
26888
26890
  }
26889
26891
  function dictDelete(dict, key) {
26892
+ if (dict.storedEntries) throw new TypeError("Stored dictionary requires asynchronous access");
26890
26893
  for (let i = dict.entries.length - 1; i >= 0; i--) {
26891
26894
  if (dict.entries[i].key.decoded === key) {
26892
26895
  dict.entries.splice(i, 1);
@@ -27536,6 +27539,60 @@ function getStandardFontOutlines(name, options = {}) {
27536
27539
  return font;
27537
27540
  }
27538
27541
 
27542
+ // packages/pdf-ast/src/cos/compact-number.ts
27543
+ var CompactPdfNumber = class {
27544
+ original = "";
27545
+ sign = "";
27546
+ digits = "";
27547
+ significant = 0;
27548
+ fractional = 0;
27549
+ decimal = false;
27550
+ exponent = false;
27551
+ exponentNegative = false;
27552
+ power = 0n;
27553
+ sticky = false;
27554
+ append(character) {
27555
+ const text = String.fromCharCode(character);
27556
+ if (this.original !== void 0) this.original = this.original.length < 2048 ? this.original + text : void 0;
27557
+ if (character === 69 || character === 101) {
27558
+ this.exponent = true;
27559
+ return;
27560
+ }
27561
+ if (character === 43 || character === 45) {
27562
+ if (this.exponent) this.exponentNegative = character === 45;
27563
+ else this.sign = text;
27564
+ return;
27565
+ }
27566
+ if (character === 46) {
27567
+ this.decimal = true;
27568
+ return;
27569
+ }
27570
+ const digit2 = character - 48;
27571
+ if (this.exponent) {
27572
+ const maximum10 = 2n * BigInt(Number.MAX_SAFE_INTEGER);
27573
+ if (this.power < maximum10) {
27574
+ this.power = this.power * 10n + BigInt(digit2);
27575
+ if (this.power > maximum10) this.power = maximum10;
27576
+ }
27577
+ return;
27578
+ }
27579
+ if (this.decimal) this.fractional++;
27580
+ if (!this.significant && digit2 === 0) return;
27581
+ this.significant++;
27582
+ if (this.digits.length < 2048) this.digits += text;
27583
+ else if (digit2 !== 0) this.sticky = true;
27584
+ }
27585
+ get spelling() {
27586
+ if (this.original !== void 0) return this.original;
27587
+ const digits = (this.digits || "0") + (this.sticky ? "1" : "");
27588
+ const power = (this.exponentNegative ? -this.power : this.power) + BigInt(this.significant - this.digits.length - this.fractional) - (this.sticky ? 1n : 0n);
27589
+ return `${this.sign}${digits}e${power}`;
27590
+ }
27591
+ get shortened() {
27592
+ return this.original === void 0;
27593
+ }
27594
+ };
27595
+
27539
27596
  // packages/pdf-ast/src/cos/lexer.ts
27540
27597
  function isPdfWhitespace(byte3) {
27541
27598
  return byte3 === 0 || byte3 === 9 || byte3 === 10 || byte3 === 12 || byte3 === 13 || byte3 === 32;
@@ -27594,23 +27651,29 @@ var StringOutput = class {
27594
27651
  }
27595
27652
  };
27596
27653
  var CosLexerState = class {
27597
- constructor(bytes, start = 0, end = bytes.length, maxTokenBytes = Infinity, knownCommands, onTokenAllocation, stringMode = "buffer") {
27654
+ constructor(bytes, start = 0, end = bytes.length, maxTokenBytes = Infinity, knownCommands, onTokenAllocation, stringMode = "buffer", compactNumbers = false, compactKeywords = false) {
27598
27655
  this.knownCommands = knownCommands;
27599
27656
  this.onTokenAllocation = onTokenAllocation;
27600
27657
  this.stringMode = stringMode;
27658
+ this.compactNumbers = compactNumbers;
27601
27659
  this.window = bytes;
27602
27660
  this.pos = start;
27603
27661
  this.end = end;
27604
27662
  this.maxTokenBytes = maxTokenBytes;
27663
+ let keywordLimit = compactKeywords ? 64 : Infinity;
27664
+ if (compactKeywords) for (const command of knownCommands ?? []) keywordLimit = Math.max(keywordLimit, command.length);
27665
+ this.keywordLimit = keywordLimit;
27605
27666
  }
27606
27667
  knownCommands;
27607
27668
  onTokenAllocation;
27608
27669
  stringMode;
27670
+ compactNumbers;
27609
27671
  window;
27610
27672
  windowStart = 0;
27611
27673
  pos;
27612
27674
  end;
27613
27675
  maxTokenBytes;
27676
+ keywordLimit;
27614
27677
  *byte(position) {
27615
27678
  if (position < 0 || position >= this.end) return void 0;
27616
27679
  if (position < this.windowStart || position >= this.windowStart + this.window.length) {
@@ -27694,14 +27757,17 @@ var CosLexerState = class {
27694
27757
  this.pos++;
27695
27758
  return { kind: "keyword", value: String.fromCharCode(b), span: { start, end: this.pos } };
27696
27759
  }
27697
- let raw = "";
27760
+ let raw = "", truncated = false;
27698
27761
  while (this.pos < this.end) {
27699
- const cur = yield* this.byte(this.pos);
27762
+ const cur = this.window[this.pos - this.windowStart] ?? (yield* this.byte(this.pos));
27700
27763
  if (isPdfWhitespace(cur) || isPdfDelimiter(cur)) break;
27701
- this.onTokenAllocation?.(32);
27702
- const next = raw + String.fromCharCode(cur);
27703
- if (this.knownCommands?.has(raw) && !this.knownCommands.has(next)) break;
27704
- raw = next;
27764
+ if (!truncated) {
27765
+ this.onTokenAllocation?.(32);
27766
+ const next = raw + String.fromCharCode(cur);
27767
+ if (this.knownCommands?.has(raw) && !this.knownCommands.has(next)) break;
27768
+ if (next.length > this.keywordLimit) truncated = true;
27769
+ else raw = next;
27770
+ }
27705
27771
  this.pos++;
27706
27772
  if (this.pos - start > this.maxTokenBytes) {
27707
27773
  throw new PdfError("E_LIMIT", "PDF token exceeds maximum byte length");
@@ -27711,13 +27777,18 @@ var CosLexerState = class {
27711
27777
  if (raw === "true") return { kind: "boolean", value: true, span };
27712
27778
  if (raw === "false") return { kind: "boolean", value: false, span };
27713
27779
  if (raw === "null") return { kind: "null", span };
27714
- return { kind: "keyword", value: raw, span };
27780
+ return { kind: "keyword", value: truncated ? raw + "\u2026" : raw, ...truncated ? { truncated: true } : {}, span };
27715
27781
  }
27716
27782
  *readNumber() {
27717
27783
  const start = this.pos;
27784
+ const compact = this.compactNumbers ? new CompactPdfNumber() : void 0;
27785
+ if (compact) this.onTokenAllocation?.(16384);
27718
27786
  const advance = (character) => {
27719
- this.onTokenAllocation?.(32);
27720
- if (character !== void 0) normalized += String.fromCharCode(character);
27787
+ if (!compact) this.onTokenAllocation?.(32);
27788
+ if (character !== void 0) {
27789
+ if (compact) compact.append(character);
27790
+ else normalized += String.fromCharCode(character);
27791
+ }
27721
27792
  this.pos++;
27722
27793
  if (this.pos - start > this.maxTokenBytes) {
27723
27794
  throw new PdfError("E_LIMIT", "PDF token exceeds maximum byte length");
@@ -27751,7 +27822,7 @@ var CosLexerState = class {
27751
27822
  throw new PdfError("E_PARSE", "Invalid PDF number prefix");
27752
27823
  }
27753
27824
  while (this.pos < this.end) {
27754
- const b = yield* this.byte(this.pos);
27825
+ const b = this.window[this.pos - this.windowStart] ?? (yield* this.byte(this.pos));
27755
27826
  if (b >= 48 && b <= 57) {
27756
27827
  advance(b);
27757
27828
  } else if (b === 46 && !decimal) {
@@ -27776,6 +27847,7 @@ var CosLexerState = class {
27776
27847
  }
27777
27848
  }
27778
27849
  }
27850
+ if (compact) normalized = compact.spelling;
27779
27851
  const value = Number(normalized);
27780
27852
  if (!Number.isFinite(value)) {
27781
27853
  throw new PdfError("E_CAPABILITY", `Non-finite PDF number: ${normalized}`);
@@ -27783,7 +27855,7 @@ var CosLexerState = class {
27783
27855
  return {
27784
27856
  kind: "number",
27785
27857
  value,
27786
- raw: exponent ? formatPdfNumber(value) : normalized,
27858
+ raw: exponent ? formatPdfNumber(value) : compact?.shortened ? `${Object.is(value, -0) ? "-0" : formatPdfNumber(value)}${decimal && Number.isInteger(value) ? ".0" : ""}` : normalized,
27787
27859
  isInteger: Number.isInteger(value) && !decimal && !exponent,
27788
27860
  span: { start, end: this.pos }
27789
27861
  };
@@ -27962,7 +28034,9 @@ var CosRangeLexer = class {
27962
28034
  maximum10,
27963
28035
  options.knownCommands,
27964
28036
  options.onTokenAllocation,
27965
- options.stringStorage ? "count" : "buffer"
28037
+ options.stringStorage ? "count" : "buffer",
28038
+ options.compactNumbers,
28039
+ options.compactKeywords
27966
28040
  );
27967
28041
  this.onBackingError = options.onBackingError;
27968
28042
  this.onTokenAllocation = options.onTokenAllocation;
@@ -28208,7 +28282,7 @@ function* parseValueSteps(lexer, maxDepth, repair = false, maxNodes = Infinity,
28208
28282
  } else if (parent?.kind === "dict" && !parent.key) {
28209
28283
  if (tok.kind === "dict-end") {
28210
28284
  yield* pop();
28211
- node = yield { kind: "dict", entries: parent.entries, span: { start: parent.start, end: tok.span.end } };
28285
+ node = yield { kind: "dict", entries: parent.entries, ...parent.storedEntries ? { storedEntries: parent.storedEntries } : {}, span: { start: parent.start, end: tok.span.end } };
28212
28286
  } else if (tok.kind === "name") {
28213
28287
  charge();
28214
28288
  parent.key = { kind: "name", rawBytes: tok.rawBytes, decoded: tok.decoded, span: tok.span };
@@ -28236,7 +28310,15 @@ function* parseValueSteps(lexer, maxDepth, repair = false, maxNodes = Infinity,
28236
28310
  continue;
28237
28311
  }
28238
28312
  if (tok.kind === "dict-start") {
28239
- yield* push({ kind: "dict", path: ancestorPath(parent), start: tok.span.start, entries: [] });
28313
+ const backed = options.dictionaryStorage && (parent?.kind === "dict" && !parent.storedEntries && options.storedDictionaryKeys?.includes(parent.key.decoded) || !parent && options.storeRootDictionary);
28314
+ yield* push({
28315
+ kind: "dict",
28316
+ path: ancestorPath(parent),
28317
+ start: tok.span.start,
28318
+ entries: [],
28319
+ tail: -1,
28320
+ ...backed ? { storedEntries: { storage: options.dictionaryStorage, position: -1, length: 0 } } : {}
28321
+ });
28240
28322
  continue;
28241
28323
  }
28242
28324
  node = yield* parseLeafFromToken(tok, lexer);
@@ -28250,7 +28332,12 @@ function* parseValueSteps(lexer, maxDepth, repair = false, maxNodes = Infinity,
28250
28332
  container.tail = position;
28251
28333
  } else container.items.push(node);
28252
28334
  } else {
28253
- container.entries.push({ key: container.key, value: node });
28335
+ const entry = { key: container.key, value: node };
28336
+ if (container.storedEntries) {
28337
+ const position = yield { kind: "dictionary-append", entry, previous: container.tail };
28338
+ container.storedEntries = { ...container.storedEntries, position: container.tail === -1 ? position : container.storedEntries.position, length: container.storedEntries.length + 1 };
28339
+ container.tail = position;
28340
+ } else container.entries.push(entry);
28254
28341
  delete container.key;
28255
28342
  }
28256
28343
  }
@@ -28322,6 +28409,442 @@ function assertDecodedByteBudget(byteLength, maxBytes = Infinity) {
28322
28409
  }
28323
28410
  }
28324
28411
 
28412
+ // packages/pdf-ast/src/cos/object-index.ts
28413
+ import { listenForAbort } from "@poe-platform/safe-fs/contracts";
28414
+ var recordBytes = 32;
28415
+ function integer(value, name) {
28416
+ if (!Number.isSafeInteger(value) || value < 0) throw new RangeError(`Invalid ${name}`);
28417
+ return value;
28418
+ }
28419
+ function budget(value, name) {
28420
+ return value === void 0 || value === Infinity ? Infinity : integer(value, name);
28421
+ }
28422
+ function fields(entry) {
28423
+ const key = integer(entry.objectNumber, "PDF object number");
28424
+ if (entry.type === "free") return [key, integer(entry.nextFreeObjectNumber ?? 0, "free object number"), integer(entry.generationNumber ?? 0, "generation number"), 0];
28425
+ if (entry.type === "uncompressed") return [key, integer(entry.offset, "object offset"), integer(entry.generationNumber ?? 0, "generation number"), 1];
28426
+ if (entry.type === "compressed") return [key, integer(entry.objectStreamNumber, "object stream number"), integer(entry.indexInStream ?? entry.indexInObjectStream, "object stream index"), 2];
28427
+ throw new PdfError("E_PARSE", "Invalid PDF cross-reference entry type");
28428
+ }
28429
+ function decode(bytes, offset = 0) {
28430
+ const view = new DataView(bytes.buffer, bytes.byteOffset + offset, recordBytes);
28431
+ const objectNumber = view.getFloat64(0);
28432
+ const first = view.getFloat64(8);
28433
+ const second = view.getFloat64(16);
28434
+ const type = view.getFloat64(24);
28435
+ if (type === 0) return { objectNumber, type: "free", nextFreeObjectNumber: first, generationNumber: second };
28436
+ if (type === 1) return { objectNumber, type: "uncompressed", offset: first, generationNumber: second };
28437
+ if (type === 2) return { objectNumber, type: "compressed", objectStreamNumber: first, indexInStream: second };
28438
+ throw new PdfError("E_PARSE", "Invalid staged PDF index record");
28439
+ }
28440
+ async function* encode2(entries, chunkBytes) {
28441
+ let bytes = new Uint8Array(chunkBytes);
28442
+ let offset = 0;
28443
+ for await (const entry of entries) {
28444
+ const view = new DataView(bytes.buffer, offset, recordBytes);
28445
+ const values = fields(entry);
28446
+ for (let i = 0; i < values.length; i++) view.setFloat64(i * 8, values[i]);
28447
+ offset += recordBytes;
28448
+ if (offset === bytes.length) {
28449
+ yield bytes;
28450
+ bytes = new Uint8Array(chunkBytes);
28451
+ offset = 0;
28452
+ }
28453
+ }
28454
+ if (offset) yield bytes.subarray(0, offset);
28455
+ }
28456
+ async function* records(source, signal) {
28457
+ for await (const bytes of source.stream(0, source.size, signal)) {
28458
+ if (bytes.length % recordBytes !== 0) throw new PdfError("E_PARSE", "Truncated staged PDF index");
28459
+ for (let offset = 0; offset < bytes.length; offset += recordBytes) {
28460
+ signal?.throwIfAborted();
28461
+ yield decode(bytes, offset);
28462
+ }
28463
+ }
28464
+ }
28465
+ async function* merge(first, second, duplicate, signal) {
28466
+ const left = records(first, signal);
28467
+ const right = records(second, signal);
28468
+ try {
28469
+ let a = await left.next();
28470
+ let b = await right.next();
28471
+ let turns = 0;
28472
+ while (!a.done || !b.done) {
28473
+ signal?.throwIfAborted();
28474
+ if (!a.done && (b.done || a.value.objectNumber <= b.value.objectNumber)) {
28475
+ const equal2 = !b.done && a.value.objectNumber === b.value.objectNumber;
28476
+ yield equal2 && duplicate === "last" && !b.done ? b.value : a.value;
28477
+ if (equal2) b = await right.next();
28478
+ a = await left.next();
28479
+ } else if (!b.done) {
28480
+ yield b.value;
28481
+ b = await right.next();
28482
+ }
28483
+ if (++turns % 1024 === 0) await new Promise((resolve2) => setTimeout(resolve2, 0));
28484
+ }
28485
+ } finally {
28486
+ await left.return(void 0);
28487
+ await right.return(void 0);
28488
+ }
28489
+ }
28490
+ var PdfObjectIndex = class _PdfObjectIndex {
28491
+ constructor(source, signal) {
28492
+ this.source = source;
28493
+ this.signal = signal;
28494
+ }
28495
+ source;
28496
+ signal;
28497
+ closing;
28498
+ get size() {
28499
+ return this.source.size / recordBytes;
28500
+ }
28501
+ static async build(input, storage, options = {}) {
28502
+ const duplicate = options.duplicate ?? "first";
28503
+ if (duplicate !== "first" && duplicate !== "last") throw new RangeError("Invalid PDF index duplicate policy");
28504
+ const runEntries = integer(options.runEntries ?? 2048, "runEntries");
28505
+ const chunkBytes = integer(options.chunkBytes ?? 64 * 1024, "chunkBytes");
28506
+ const cacheBytes = integer(options.cacheBytes ?? 256 * 1024, "cacheBytes");
28507
+ if (!runEntries || chunkBytes < recordBytes || chunkBytes % recordBytes !== 0 || cacheBytes < chunkBytes) throw new RangeError("Invalid PDF index batch/cache sizes");
28508
+ const maxEntries = budget(options.maxEntries, "maxEntries");
28509
+ const maxStagingBytes = budget(options.maxStagingBytes, "maxStagingBytes");
28510
+ const { signal } = options;
28511
+ signal?.throwIfAborted();
28512
+ const owned = /* @__PURE__ */ new Set();
28513
+ const levels = [];
28514
+ let stagedBytes = 0;
28515
+ let admitted = 0;
28516
+ let batch = [];
28517
+ const dispose = async (source) => {
28518
+ try {
28519
+ await source.close();
28520
+ } finally {
28521
+ owned.delete(source);
28522
+ stagedBytes -= source.size;
28523
+ }
28524
+ };
28525
+ const stage = async (entries) => {
28526
+ let reserved = 0;
28527
+ async function* chunks() {
28528
+ for await (const bytes of encode2(entries, chunkBytes)) {
28529
+ signal?.throwIfAborted();
28530
+ if (bytes.length > Math.min(maxStagingBytes, Number.MAX_SAFE_INTEGER) - stagedBytes) throw new PdfError("E_LIMIT", "PDF index staging byte limit exceeded");
28531
+ stagedBytes += bytes.length;
28532
+ reserved += bytes.length;
28533
+ yield bytes;
28534
+ }
28535
+ }
28536
+ try {
28537
+ const source = await PdfFileSource.fromStream(storage.fs, storage.directory, chunks(), { chunkBytes, cacheBytes, ...signal ? { signal } : {} });
28538
+ owned.add(source);
28539
+ return source;
28540
+ } catch (error) {
28541
+ stagedBytes -= reserved;
28542
+ throw error;
28543
+ }
28544
+ };
28545
+ const flush = async () => {
28546
+ if (duplicate === "last") batch.reverse();
28547
+ batch.sort((a, b) => a.objectNumber - b.objectNumber);
28548
+ const sorted = batch;
28549
+ batch = [];
28550
+ function* unique() {
28551
+ let previous = -1;
28552
+ for (const entry of sorted) if (entry.objectNumber !== previous) {
28553
+ previous = entry.objectNumber;
28554
+ yield entry;
28555
+ }
28556
+ }
28557
+ let run = await stage(unique());
28558
+ let level = 0;
28559
+ while (levels[level]) {
28560
+ const earlier = levels[level];
28561
+ const combined = await stage(merge(earlier, run, duplicate, signal));
28562
+ await dispose(earlier);
28563
+ await dispose(run);
28564
+ levels[level++] = void 0;
28565
+ run = combined;
28566
+ }
28567
+ levels[level] = run;
28568
+ };
28569
+ const iterator = Symbol.asyncIterator in input ? input[Symbol.asyncIterator]() : input[Symbol.iterator]();
28570
+ let ended = false;
28571
+ const next = async () => {
28572
+ signal?.throwIfAborted();
28573
+ if (!signal) return iterator.next();
28574
+ let dispose2 = () => {
28575
+ };
28576
+ const cancelled = new Promise((ignored, reject) => {
28577
+ dispose2 = listenForAbort(signal, () => reject(signal.reason));
28578
+ });
28579
+ const pending = Promise.resolve().then(() => {
28580
+ signal.throwIfAborted();
28581
+ return iterator.next();
28582
+ });
28583
+ try {
28584
+ return await Promise.race([pending, cancelled]);
28585
+ } finally {
28586
+ dispose2();
28587
+ }
28588
+ };
28589
+ try {
28590
+ while (true) {
28591
+ const step = await next();
28592
+ signal?.throwIfAborted();
28593
+ if (step.done) {
28594
+ ended = true;
28595
+ break;
28596
+ }
28597
+ if (admitted >= Math.min(maxEntries, Number.MAX_SAFE_INTEGER)) throw new PdfError("E_LIMIT", "PDF index entry limit exceeded");
28598
+ admitted++;
28599
+ const values = fields(step.value);
28600
+ const entry = step.value.type === "compressed" ? { objectNumber: values[0], type: "compressed", objectStreamNumber: values[1], indexInStream: values[2] } : step.value.type === "free" ? { objectNumber: values[0], type: "free", nextFreeObjectNumber: values[1], generationNumber: values[2] } : { objectNumber: values[0], type: "uncompressed", offset: values[1], generationNumber: values[2] };
28601
+ batch.push(entry);
28602
+ if (batch.length === runEntries) await flush();
28603
+ if (admitted % 1024 === 0) await new Promise((resolve2) => setTimeout(resolve2, 0));
28604
+ }
28605
+ if (batch.length) await flush();
28606
+ let result;
28607
+ for (let level = levels.length - 1; level >= 0; level--) {
28608
+ const run = levels[level];
28609
+ if (!run) continue;
28610
+ if (!result) result = run;
28611
+ else {
28612
+ const combined = await stage(merge(result, run, duplicate, signal));
28613
+ await dispose(result);
28614
+ await dispose(run);
28615
+ result = combined;
28616
+ }
28617
+ }
28618
+ result ??= await stage([]);
28619
+ signal?.throwIfAborted();
28620
+ owned.delete(result);
28621
+ return new _PdfObjectIndex(result, signal);
28622
+ } catch (error) {
28623
+ for (const source of owned) {
28624
+ try {
28625
+ await source.close();
28626
+ } catch {
28627
+ }
28628
+ }
28629
+ throw error;
28630
+ } finally {
28631
+ if (!ended) {
28632
+ try {
28633
+ const returning = iterator.return?.();
28634
+ if (returning) {
28635
+ if (signal?.aborted) void Promise.resolve(returning).catch(() => {
28636
+ });
28637
+ else await returning;
28638
+ }
28639
+ } catch {
28640
+ }
28641
+ }
28642
+ }
28643
+ }
28644
+ async get(objectNumber, signal) {
28645
+ integer(objectNumber, "PDF object number");
28646
+ this.assertOpen(signal);
28647
+ let low = 0;
28648
+ let high = this.size;
28649
+ while (low < high) {
28650
+ const middle = low + Math.floor((high - low) / 2);
28651
+ const entry = decode(await this.source.read(middle * recordBytes, recordBytes, signal));
28652
+ this.assertOpen(signal);
28653
+ if (entry.objectNumber === objectNumber) return entry;
28654
+ if (entry.objectNumber < objectNumber) low = middle + 1;
28655
+ else high = middle;
28656
+ }
28657
+ return void 0;
28658
+ }
28659
+ assertOpen(signal) {
28660
+ this.signal?.throwIfAborted();
28661
+ signal?.throwIfAborted();
28662
+ if (this.closing) throw new PdfError("E_CAPABILITY", "PDF object index is closed");
28663
+ }
28664
+ async *entries(signal) {
28665
+ this.assertOpen(signal);
28666
+ for await (const entry of records(this.source, signal)) {
28667
+ this.assertOpen(signal);
28668
+ yield entry;
28669
+ }
28670
+ }
28671
+ close() {
28672
+ this.closing ??= this.source.close();
28673
+ return this.closing;
28674
+ }
28675
+ };
28676
+
28677
+ // packages/pdf-ast/src/cos/name-index.ts
28678
+ var PdfNameIndex = class {
28679
+ constructor(storage, maximum10 = Infinity, signal) {
28680
+ this.storage = storage;
28681
+ this.maximum = maximum10;
28682
+ this.signal = signal;
28683
+ const limit10 = typeof maximum10 === "function" ? maximum10() : maximum10;
28684
+ if (limit10 !== Infinity && (!Number.isSafeInteger(limit10) || limit10 < 0)) throw new RangeError("Invalid name staging limit");
28685
+ }
28686
+ storage;
28687
+ maximum;
28688
+ signal;
28689
+ tail = /* @__PURE__ */ new Map();
28690
+ hot = /* @__PURE__ */ new Map();
28691
+ levels = [];
28692
+ nextNode = 2;
28693
+ nextName = 0;
28694
+ closed = false;
28695
+ get stagedBytes() {
28696
+ return this.levels.reduce((sum, index2) => sum + (index2?.size ?? 0) * 32, 0);
28697
+ }
28698
+ async get(edge) {
28699
+ if (this.tail.has(edge)) return this.tail.get(edge);
28700
+ if (this.hot.has(edge)) return this.hot.get(edge);
28701
+ for (const level of this.levels) {
28702
+ const entry = await level?.get(edge, this.signal);
28703
+ if (entry) {
28704
+ if (this.hot.size < 256) this.hot.set(edge, entry.offset);
28705
+ return entry.offset;
28706
+ }
28707
+ }
28708
+ return void 0;
28709
+ }
28710
+ async insert(edge, node) {
28711
+ this.tail.set(edge, node);
28712
+ if (this.hot.size < 256) this.hot.set(edge, node);
28713
+ if (this.tail.size < 64) return;
28714
+ let level = 0;
28715
+ while (this.levels[level]) level++;
28716
+ const inputs = this.levels.slice(0, level);
28717
+ const tail = this.tail;
28718
+ const signal = this.signal;
28719
+ async function* rows() {
28720
+ for (const [objectNumber, offset] of tail) yield { objectNumber, offset, type: "uncompressed" };
28721
+ for (const index2 of inputs) yield* index2.entries(signal);
28722
+ }
28723
+ const limit10 = typeof this.maximum === "function" ? this.maximum() : this.maximum;
28724
+ const remaining = Math.min(limit10, Number.MAX_SAFE_INTEGER) - this.stagedBytes;
28725
+ if (remaining < 0) throw new PdfError("E_LIMIT", "PDF name staging byte limit exceeded");
28726
+ const combined = await PdfObjectIndex.build(rows(), this.storage, {
28727
+ runEntries: 64,
28728
+ chunkBytes: 2048,
28729
+ cacheBytes: 2048,
28730
+ maxStagingBytes: remaining,
28731
+ ...signal ? { signal } : {}
28732
+ });
28733
+ try {
28734
+ for (let i = 0; i < level; i++) {
28735
+ await this.levels[i].close();
28736
+ this.levels[i] = void 0;
28737
+ }
28738
+ this.levels[level] = combined;
28739
+ this.tail.clear();
28740
+ } catch (error) {
28741
+ try {
28742
+ await combined.close();
28743
+ } catch {
28744
+ }
28745
+ throw error;
28746
+ }
28747
+ }
28748
+ async intern(value) {
28749
+ if (this.closed) throw new PdfError("E_CAPABILITY", "PDF name index is closed");
28750
+ this.signal?.throwIfAborted();
28751
+ let node = 1, newPath = false;
28752
+ const units = typeof value === "string" ? (function* () {
28753
+ for (let i = 0; i < value.length; i++) yield value.charCodeAt(i);
28754
+ })() : value;
28755
+ let work = 0;
28756
+ for await (const code of units) {
28757
+ this.signal?.throwIfAborted();
28758
+ if (!Number.isInteger(code) || code < 0 || code > 65535) throw new RangeError("Invalid PDF name code unit");
28759
+ if (++work % 512 === 0) {
28760
+ await new Promise((resolve2) => setTimeout(resolve2, 0));
28761
+ this.signal?.throwIfAborted();
28762
+ }
28763
+ for (const unit of [code & 255, code >>> 8]) {
28764
+ const edge = node * 257 + unit + 1;
28765
+ let child = newPath ? void 0 : await this.get(edge);
28766
+ if (child === void 0) {
28767
+ if (this.nextNode > Math.floor(Number.MAX_SAFE_INTEGER / 257) - 1) throw new PdfError("E_LIMIT", "PDF name index address limit exceeded");
28768
+ child = this.nextNode++;
28769
+ await this.insert(edge, child);
28770
+ newPath = true;
28771
+ }
28772
+ node = child;
28773
+ }
28774
+ }
28775
+ const terminal = node * 257;
28776
+ const existing = newPath ? void 0 : await this.get(terminal);
28777
+ if (existing !== void 0) return { index: existing, added: false };
28778
+ const index2 = this.nextName++;
28779
+ await this.insert(terminal, index2);
28780
+ return { index: index2, added: true };
28781
+ }
28782
+ async close() {
28783
+ if (this.closed) return;
28784
+ this.closed = true;
28785
+ const results = await Promise.allSettled(this.levels.map((index2) => index2?.close()));
28786
+ this.tail.clear();
28787
+ this.hot.clear();
28788
+ this.levels.length = 0;
28789
+ for (const result of results) if (result.status === "rejected") throw result.reason;
28790
+ }
28791
+ };
28792
+
28793
+ // packages/pdf-ast/src/content/stored-dictionary.ts
28794
+ async function* readPdfDictionaryEntries(dict, signal) {
28795
+ signal?.throwIfAborted();
28796
+ if (dict.storedEntries) yield* readStoredItems(dict.storedEntries, signal);
28797
+ else for (const entry of dict.entries) {
28798
+ signal?.throwIfAborted();
28799
+ yield entry;
28800
+ }
28801
+ }
28802
+ async function readPdfDictionaryValue(dict, key, signal) {
28803
+ let value;
28804
+ for await (const entry of readPdfDictionaryEntries(dict, signal)) if (entry.key.decoded === key) value = entry.value;
28805
+ return value;
28806
+ }
28807
+ async function mergePdfResourceDictionaries(destination, source, indexStorage, signal) {
28808
+ const storage = destination.storedEntries?.storage ?? source?.storedEntries?.storage;
28809
+ if (!storage) throw new TypeError("Resource merge requires caller-backed entries");
28810
+ const names = new PdfNameIndex(indexStorage, Infinity, signal);
28811
+ let index2, failed = false;
28812
+ async function* rows() {
28813
+ for (const [dict, replace] of [[destination, true], [source, false]]) {
28814
+ if (!dict) continue;
28815
+ for await (const entry of readPdfDictionaryEntries(dict, signal)) {
28816
+ const name = await names.intern(entry.key.decoded);
28817
+ if (!replace && !name.added) continue;
28818
+ const position = await writeStoredRecord(storage, entry, -1, signal);
28819
+ yield { objectNumber: name.index, type: "uncompressed", offset: position };
28820
+ }
28821
+ }
28822
+ }
28823
+ try {
28824
+ index2 = await PdfObjectIndex.build(rows(), indexStorage, { duplicate: "last", runEntries: 64, chunkBytes: 2048, cacheBytes: 2048, ...signal ? { signal } : {} });
28825
+ let position = -1, previous = -1, length = 0;
28826
+ const link2 = new Uint8Array(8), view = new DataView(link2.buffer);
28827
+ for await (const row of index2.entries(signal)) {
28828
+ if (previous !== -1) {
28829
+ view.setFloat64(0, row.offset, true);
28830
+ await storage.write(previous, link2, signal ? { signal } : void 0);
28831
+ signal?.throwIfAborted();
28832
+ } else position = row.offset;
28833
+ previous = row.offset;
28834
+ length++;
28835
+ }
28836
+ return { kind: "dict", entries: [], storedEntries: { storage, position, length } };
28837
+ } catch (error) {
28838
+ failed = true;
28839
+ throw error;
28840
+ } finally {
28841
+ const results = await Promise.allSettled([index2?.close(), names.close()]);
28842
+ if (!failed) {
28843
+ for (const result of results) if (result.status === "rejected") await Promise.reject(result.reason);
28844
+ }
28845
+ }
28846
+ }
28847
+
28325
28848
  // packages/pdf-ast/src/cos/security.ts
28326
28849
  import { readBytes as readBytes11 } from "@poe-platform/safe-fs/contracts";
28327
28850
 
@@ -30375,9 +30898,23 @@ async function decryptPdfObjectStrings(state, objectNumber, generationNumber, va
30375
30898
  }
30376
30899
  if (node.kind === "dict") {
30377
30900
  const entries = [];
30378
- const signature = isSignatureDictionary(node);
30379
- for (const entry of node.entries) entries.push({ key: entry.key, value: signature && entry.key.decoded === "Contents" ? entry.value : await transform(entry.value) });
30380
- return { ...node, entries };
30901
+ let signatureDict = node;
30902
+ if (node.storedEntries) {
30903
+ signatureDict = { kind: "dict", entries: [] };
30904
+ for await (const entry of readPdfDictionaryEntries(node, options.signal)) {
30905
+ if (["Type", "FT", "ByteRange", "Filter"].includes(entry.key.decoded)) dictSet(signatureDict, entry.key.decoded, entry.value);
30906
+ }
30907
+ }
30908
+ const signature = isSignatureDictionary(signatureDict);
30909
+ let position = -1, tail = -1;
30910
+ for await (const entry of readPdfDictionaryEntries(node, options.signal)) {
30911
+ const transformed = { key: entry.key, value: signature && entry.key.decoded === "Contents" ? entry.value : await transform(entry.value) };
30912
+ if (node.storedEntries) {
30913
+ tail = await appendStoredRecord(node.storedEntries.storage, transformed, tail, options.signal);
30914
+ if (position === -1) position = tail;
30915
+ } else entries.push(transformed);
30916
+ }
30917
+ return { ...node, entries, ...node.storedEntries ? { storedEntries: { ...node.storedEntries, position } } : {} };
30381
30918
  }
30382
30919
  return drainWorkAsync(transformNodeStringsAndStreamsSteps(node, (bytes) => decryptPdfBuffer(state, objectNumber, generationNumber, bytes)), options.signal);
30383
30920
  }
@@ -31707,6 +32244,35 @@ function* annotationNameDestinationSteps(first, name, maxDepth = Infinity) {
31707
32244
  }
31708
32245
  }
31709
32246
 
32247
+ // packages/pdf-ast/src/content/dictionary-cursor.ts
32248
+ var PdfDictionaryCursor = class {
32249
+ constructor(dict) {
32250
+ this.dict = dict;
32251
+ this.length = dict.storedEntries?.length ?? dict.entries.length;
32252
+ if (!Number.isSafeInteger(this.length) || this.length < 0) throw new RangeError("Invalid stored dictionary length");
32253
+ this.position = dict.storedEntries?.position ?? -1;
32254
+ }
32255
+ dict;
32256
+ index = 0;
32257
+ position;
32258
+ length;
32259
+ *next() {
32260
+ if (this.index === this.length) {
32261
+ if (this.dict.storedEntries && this.position !== -1) throw new Error("Invalid stored dictionary terminator");
32262
+ return { done: true, value: void 0 };
32263
+ }
32264
+ let entry = this.dict.entries[this.index];
32265
+ if (this.dict.storedEntries) {
32266
+ const reply = yield { kind: "dictionary-entry", entries: this.dict.storedEntries, position: this.position };
32267
+ if (reply?.kind !== "array" || reply.items[0]?.kind !== "name" || !reply.items[1] || reply.items[2]?.kind !== "number") throw new TypeError("Expected a PDF dictionary record");
32268
+ entry = { key: reply.items[0], value: reply.items[1] };
32269
+ this.position = reply.items[2].value;
32270
+ }
32271
+ this.index++;
32272
+ return { done: false, value: entry };
32273
+ }
32274
+ };
32275
+
31710
32276
  // packages/pdf-ast/src/fonts/stored-widths.ts
31711
32277
  import { IntegerTable } from "@poe-platform/safe-fs/storage";
31712
32278
  var StoredFontWidths = class {
@@ -32693,13 +33259,13 @@ function embedTrueTypeFontInCos(doc, font, usedGlyphs) {
32693
33259
  }
32694
33260
 
32695
33261
  // packages/pdf-ast/src/fonts/resolve.ts
32696
- function* resolve(node, storeRootArray = false) {
32697
- const value = yield { kind: "resolve", node, storeRootArray };
33262
+ function* resolve(node, storeRootArray = false, storeRootDictionary = false) {
33263
+ const value = yield { kind: "resolve", node, storeRootArray, storeRootDictionary };
32698
33264
  if (value && !("kind" in value)) throw new TypeError("Font lookup returned stream bytes instead of a COS value");
32699
33265
  return value;
32700
33266
  }
32701
- function* resolveDict2(node) {
32702
- const value = yield* resolve(node);
33267
+ function* resolveDict2(node, backed = false) {
33268
+ const value = yield* resolve(node, false, backed);
32703
33269
  return value?.kind === "dict" ? value : value?.kind === "stream" ? value.dict : void 0;
32704
33270
  }
32705
33271
  function* resolveArray2(node, backed = false) {
@@ -32732,287 +33298,288 @@ function* resolvePageFontsSteps(rootRef, resourcesDict, selectedName, options =
32732
33298
  const catalog = yield* resolveDict2(rootRef);
32733
33299
  const acroForm = catalog ? yield* resolveDict2(dictGet(catalog, "AcroForm")) : void 0;
32734
33300
  const drDict = acroForm ? yield* resolveDict2(dictGet(acroForm, "DR")) : void 0;
32735
- const drFontDict = drDict ? yield* resolveDict2(dictGet(drDict, "Font")) : void 0;
32736
- const pageFontDict = resourcesDict ? yield* resolveDict2(dictGet(resourcesDict, "Font")) : void 0;
32737
- function* entries() {
32738
- if (drFontDict)
32739
- yield* drFontDict.entries;
32740
- if (pageFontDict)
32741
- yield* pageFontDict.entries;
32742
- }
32743
- for (const entry of entries()) {
32744
- const fName = entry.key.decoded;
32745
- if (selectedName !== void 0 && fName !== selectedName)
32746
- continue;
32747
- const fObj = yield* resolveDict2(entry.value);
32748
- if (!fObj)
32749
- continue;
32750
- allocation.admit(1024);
32751
- const subtypeNode = yield* resolve(dictGet(fObj, "Subtype"));
32752
- const subtype = subtypeNode?.kind === "name" ? subtypeNode.decoded : "Type1";
32753
- const baseFontNode = yield* resolve(dictGet(fObj, "BaseFont"));
32754
- const baseFont = baseFontNode?.kind === "name" ? baseFontNode.decoded : "Helvetica";
32755
- let cmap;
32756
- let storedCMap;
32757
- const toUniNode = yield* resolve(dictGet(fObj, "ToUnicode"));
32758
- if (toUniNode?.kind === "stream") {
32759
- try {
32760
- const value = yield { kind: "decode", stream: toUniNode, purpose: "unicode-cmap" };
32761
- if (value instanceof Uint8Array) cmap = parseToUnicodeCMap(value, allocationOptions);
32762
- else if (value && "storedCMap" in value) storedCMap = value;
32763
- else if (value && "iterateBytes" in value) cmap = value;
32764
- else throw new TypeError("Font decoder did not return a Unicode CMap");
32765
- } catch (error) {
32766
- allocation.rethrowAllocationFailure(error);
32767
- if (error instanceof PdfError && error.code === "E_LIMIT")
32768
- throw error;
33301
+ const drFontDict = drDict ? yield* resolveDict2(dictGet(drDict, "Font"), true) : void 0;
33302
+ const pageFontDict = resourcesDict ? yield* resolveDict2(dictGet(resourcesDict, "Font"), true) : void 0;
33303
+ for (const dictionary of [drFontDict, pageFontDict]) {
33304
+ if (!dictionary) continue;
33305
+ const cursor = new PdfDictionaryCursor(dictionary);
33306
+ for (; ; ) {
33307
+ const item = yield* cursor.next();
33308
+ if (item.done) break;
33309
+ const entry = item.value;
33310
+ const fName = entry.key.decoded;
33311
+ if (selectedName !== void 0 && fName !== selectedName)
33312
+ continue;
33313
+ const fObj = yield* resolveDict2(entry.value);
33314
+ if (!fObj)
33315
+ continue;
33316
+ allocation.admit(1024);
33317
+ const subtypeNode = yield* resolve(dictGet(fObj, "Subtype"));
33318
+ const subtype = subtypeNode?.kind === "name" ? subtypeNode.decoded : "Type1";
33319
+ const baseFontNode = yield* resolve(dictGet(fObj, "BaseFont"));
33320
+ const baseFont = baseFontNode?.kind === "name" ? baseFontNode.decoded : "Helvetica";
33321
+ let cmap;
33322
+ let storedCMap;
33323
+ const toUniNode = yield* resolve(dictGet(fObj, "ToUnicode"));
33324
+ if (toUniNode?.kind === "stream") {
33325
+ try {
33326
+ const value = yield { kind: "decode", stream: toUniNode, purpose: "unicode-cmap" };
33327
+ if (value instanceof Uint8Array) cmap = parseToUnicodeCMap(value, allocationOptions);
33328
+ else if (value && "storedCMap" in value) storedCMap = value;
33329
+ else if (value && "iterateBytes" in value) cmap = value;
33330
+ else throw new TypeError("Font decoder did not return a Unicode CMap");
33331
+ } catch (error) {
33332
+ allocation.rethrowAllocationFailure(error);
33333
+ if (error instanceof PdfError && error.code === "E_LIMIT")
33334
+ throw error;
33335
+ }
32769
33336
  }
32770
- }
32771
- const encNode = yield* resolve(dictGet(fObj, "Encoding"));
32772
- if (encNode?.kind === "dict") {
32773
- const diffRef = dictGet(encNode, "Differences");
32774
- if (diffRef?.kind === "ref") {
32775
- const resolvedDiff = yield* resolve(diffRef, true);
32776
- if (resolvedDiff?.kind === "array") {
32777
- dictSet(encNode, "Differences", resolvedDiff);
32778
- }
32779
- }
32780
- }
32781
- const differenceArray = encNode?.kind === "dict" ? dictGet(encNode, "Differences") : void 0;
32782
- let storedEncoding;
32783
- if (options.resourceStorage && differenceArray?.kind === "array") {
32784
- const value = yield { kind: "font-encoding", array: differenceArray };
32785
- if (!value || !("storedEncoding" in value)) throw new TypeError("Expected stored font encoding");
32786
- storedEncoding = value;
32787
- }
32788
- allocation.admit(32768 + (!storedEncoding && differenceArray?.kind === "array" ? differenceArray.items.length * 128 : 0));
32789
- const differences = storedEncoding ? /* @__PURE__ */ new Map() : buildFontEncodingDifferencesMap(encNode);
32790
- const glyphNames = storedEncoding ? /* @__PURE__ */ new Map() : buildFontEncodingGlyphNamesMap(encNode);
32791
- function* glyphName(code) {
32792
- if (!storedEncoding) return glyphNames.get(code);
32793
- const result = yield { kind: "font-label", lookup: storedEncoding.glyphName, code };
32794
- return result && "kind" in result && result.kind === "name" ? result.decoded : void 0;
32795
- }
32796
- const widths = options.resourceStorage ? new StoredFontWidths(options.resourceStorage, { ...allocationOptions, ...options.signal ? { signal: options.signal } : {} }) : new FontWidths(allocation);
32797
- function* setWidth(first, width, last = first) {
32798
- if (widths instanceof StoredFontWidths) yield { kind: "font-width-set", widths, first, width, last };
32799
- else widths.set(first, width, last);
32800
- }
32801
- let defaultWidth = 556;
32802
- const isTwoByteCid = subtype === "Type0";
32803
- let fontMatrix;
32804
- let charProcs;
32805
- let fontResources;
32806
- if (subtype === "Type3") {
32807
- const fmArr = yield* resolveArray2(dictGet(fObj, "FontMatrix"));
32808
- if (fmArr && fmArr.items.length >= 6) {
32809
- const mn = function* (idx, fb = 0) {
32810
- const r = yield* resolve(fmArr.items[idx]);
32811
- return r?.kind === "number" ? r.value : fb;
32812
- };
32813
- fontMatrix = [yield* mn(0, 1e-3), yield* mn(1, 0), yield* mn(2, 0), yield* mn(3, 1e-3), yield* mn(4, 0), yield* mn(5, 0)];
32814
- } else {
32815
- fontMatrix = [1e-3, 0, 0, 1e-3, 0, 0];
32816
- }
32817
- charProcs = yield* resolveDict2(dictGet(fObj, "CharProcs"));
32818
- fontResources = yield* resolveDict2(dictGet(fObj, "Resources"));
32819
- }
32820
- const type3Scale1000 = subtype === "Type3" && fontMatrix ? Math.hypot(fontMatrix[0], fontMatrix[1]) * 1e3 : 1;
32821
- if (subtype === "Type0") {
32822
- const descArr = yield* resolveArray2(dictGet(fObj, "DescendantFonts"));
32823
- const cidDict = descArr && descArr.items[0] ? yield* resolveDict2(descArr.items[0]) : void 0;
32824
- if (cidDict) {
32825
- const dwNode = yield* resolve(dictGet(cidDict, "DW"));
32826
- if (dwNode?.kind === "number")
32827
- defaultWidth = dwNode.value;
32828
- const wArr = yield* resolveArray2(dictGet(cidDict, "W"), true);
32829
- if (wArr) {
32830
- const cursor = arrayCursor(wArr);
32831
- while (cursor.remaining) {
32832
- const first = yield* resolve(yield* cursor.next(), true);
32833
- const second = yield* resolve(yield* cursor.next(), true);
32834
- if (first?.kind === "number" && second?.kind === "array") {
32835
- const nested = arrayCursor(second);
32836
- for (let k = 0; nested.remaining; k++) {
32837
- const wItem = yield* resolve(yield* nested.next());
32838
- if (wItem?.kind === "number") {
32839
- yield* setWidth(first.value + k, wItem.value);
32840
- }
32841
- }
32842
- } else if (first?.kind === "number" && second?.kind === "number") {
32843
- const third = yield* resolve(yield* cursor.next(), true);
32844
- if (third?.kind === "number") {
32845
- if (!Number.isSafeInteger(first.value) || !Number.isSafeInteger(second.value))
32846
- throw new PdfError("E_LIMIT", "Unsafe PDF font width range");
32847
- yield* setWidth(first.value, third.value, second.value);
32848
- }
32849
- }
33337
+ const encNode = yield* resolve(dictGet(fObj, "Encoding"));
33338
+ if (encNode?.kind === "dict") {
33339
+ const diffRef = dictGet(encNode, "Differences");
33340
+ if (diffRef?.kind === "ref") {
33341
+ const resolvedDiff = yield* resolve(diffRef, true);
33342
+ if (resolvedDiff?.kind === "array") {
33343
+ dictSet(encNode, "Differences", resolvedDiff);
32850
33344
  }
32851
33345
  }
32852
33346
  }
32853
- } else {
32854
- const firstCharNode = yield* resolve(dictGet(fObj, "FirstChar"));
32855
- const widthsArr = yield* resolveArray2(dictGet(fObj, "Widths"), true);
32856
- if (widthsArr) {
32857
- const descriptor = yield* resolveDict2(dictGet(fObj, "FontDescriptor"));
32858
- const missingWidth = descriptor ? yield* resolve(dictGet(descriptor, "MissingWidth")) : void 0;
32859
- defaultWidth = (missingWidth?.kind === "number" ? missingWidth.value : 0) * type3Scale1000;
32860
- const firstChar = firstCharNode?.kind === "number" ? firstCharNode.value : 0;
32861
- const cursor = arrayCursor(widthsArr);
32862
- for (let k = 0; cursor.remaining; k++) {
32863
- const wItem = yield* resolve(yield* cursor.next());
32864
- if (wItem?.kind === "number") {
32865
- yield* setWidth(firstChar + k, wItem.value * type3Scale1000);
33347
+ const differenceArray = encNode?.kind === "dict" ? dictGet(encNode, "Differences") : void 0;
33348
+ let storedEncoding;
33349
+ if (options.resourceStorage && differenceArray?.kind === "array") {
33350
+ const value = yield { kind: "font-encoding", array: differenceArray };
33351
+ if (!value || !("storedEncoding" in value)) throw new TypeError("Expected stored font encoding");
33352
+ storedEncoding = value;
33353
+ }
33354
+ allocation.admit(32768 + (!storedEncoding && differenceArray?.kind === "array" ? differenceArray.items.length * 128 : 0));
33355
+ const differences = storedEncoding ? /* @__PURE__ */ new Map() : buildFontEncodingDifferencesMap(encNode);
33356
+ const glyphNames = storedEncoding ? /* @__PURE__ */ new Map() : buildFontEncodingGlyphNamesMap(encNode);
33357
+ function* glyphName(code) {
33358
+ if (!storedEncoding) return glyphNames.get(code);
33359
+ const result = yield { kind: "font-label", lookup: storedEncoding.glyphName, code };
33360
+ return result && "kind" in result && result.kind === "name" ? result.decoded : void 0;
33361
+ }
33362
+ const widths = options.resourceStorage ? new StoredFontWidths(options.resourceStorage, { ...allocationOptions, ...options.signal ? { signal: options.signal } : {} }) : new FontWidths(allocation);
33363
+ function* setWidth(first, width, last = first) {
33364
+ if (widths instanceof StoredFontWidths) yield { kind: "font-width-set", widths, first, width, last };
33365
+ else widths.set(first, width, last);
33366
+ }
33367
+ let defaultWidth = 556;
33368
+ const isTwoByteCid = subtype === "Type0";
33369
+ let fontMatrix;
33370
+ let charProcs;
33371
+ let fontResources;
33372
+ if (subtype === "Type3") {
33373
+ const fmArr = yield* resolveArray2(dictGet(fObj, "FontMatrix"));
33374
+ if (fmArr && fmArr.items.length >= 6) {
33375
+ const mn = function* (idx, fb = 0) {
33376
+ const r = yield* resolve(fmArr.items[idx]);
33377
+ return r?.kind === "number" ? r.value : fb;
33378
+ };
33379
+ fontMatrix = [yield* mn(0, 1e-3), yield* mn(1, 0), yield* mn(2, 0), yield* mn(3, 1e-3), yield* mn(4, 0), yield* mn(5, 0)];
33380
+ } else {
33381
+ fontMatrix = [1e-3, 0, 0, 1e-3, 0, 0];
33382
+ }
33383
+ charProcs = yield* resolveDict2(dictGet(fObj, "CharProcs"));
33384
+ fontResources = yield* resolveDict2(dictGet(fObj, "Resources"));
33385
+ }
33386
+ const type3Scale1000 = subtype === "Type3" && fontMatrix ? Math.hypot(fontMatrix[0], fontMatrix[1]) * 1e3 : 1;
33387
+ if (subtype === "Type0") {
33388
+ const descArr = yield* resolveArray2(dictGet(fObj, "DescendantFonts"));
33389
+ const cidDict = descArr && descArr.items[0] ? yield* resolveDict2(descArr.items[0]) : void 0;
33390
+ if (cidDict) {
33391
+ const dwNode = yield* resolve(dictGet(cidDict, "DW"));
33392
+ if (dwNode?.kind === "number")
33393
+ defaultWidth = dwNode.value;
33394
+ const wArr = yield* resolveArray2(dictGet(cidDict, "W"), true);
33395
+ if (wArr) {
33396
+ const cursor2 = arrayCursor(wArr);
33397
+ while (cursor2.remaining) {
33398
+ const first = yield* resolve(yield* cursor2.next(), true);
33399
+ const second = yield* resolve(yield* cursor2.next(), true);
33400
+ if (first?.kind === "number" && second?.kind === "array") {
33401
+ const nested = arrayCursor(second);
33402
+ for (let k = 0; nested.remaining; k++) {
33403
+ const wItem = yield* resolve(yield* nested.next());
33404
+ if (wItem?.kind === "number") {
33405
+ yield* setWidth(first.value + k, wItem.value);
33406
+ }
33407
+ }
33408
+ } else if (first?.kind === "number" && second?.kind === "number") {
33409
+ const third = yield* resolve(yield* cursor2.next(), true);
33410
+ if (third?.kind === "number") {
33411
+ if (!Number.isSafeInteger(first.value) || !Number.isSafeInteger(second.value))
33412
+ throw new PdfError("E_LIMIT", "Unsafe PDF font width range");
33413
+ yield* setWidth(first.value, third.value, second.value);
33414
+ }
33415
+ }
33416
+ }
32866
33417
  }
32867
33418
  }
32868
33419
  } else {
32869
- const stdMetrics = STANDARD_14_FONTS[normalizeStandard14FontName(baseFont)];
32870
- defaultWidth = stdMetrics.defaultWidth;
32871
- if (widths instanceof StoredFontWidths) widths.setDefaults(stdMetrics.widthsByCode);
32872
- else for (const [codeStr, wVal] of Object.entries(stdMetrics.widthsByCode)) {
32873
- yield* setWidth(Number(codeStr), wVal);
32874
- }
32875
- }
32876
- }
32877
- let embeddedCff;
32878
- let storedTrueType;
32879
- let embeddedTrueType;
32880
- let simpleToGid;
32881
- const fDescDirect = yield* resolveDict2(dictGet(fObj, "FontDescriptor"));
32882
- const descArrForTt = subtype === "Type0" ? yield* resolveArray2(dictGet(fObj, "DescendantFonts")) : void 0;
32883
- const cidDictForTt = descArrForTt && descArrForTt.items[0] ? yield* resolveDict2(descArrForTt.items[0]) : void 0;
32884
- const fDesc = fDescDirect ?? (cidDictForTt ? yield* resolveDict2(dictGet(cidDictForTt, "FontDescriptor")) : void 0);
32885
- let cidToGid;
32886
- let storedCidToGid;
32887
- const cidMap = cidDictForTt ? yield* resolve(dictGet(cidDictForTt, "CIDToGIDMap")) : void 0;
32888
- if (cidMap?.kind === "stream") {
32889
- const bytes = yield { kind: "decode", stream: cidMap, purpose: "cid-map" };
32890
- if (bytes && "byteLength" in bytes && "storage" in bytes) storedCidToGid = bytes;
32891
- else if (bytes instanceof Uint8Array) {
32892
- allocation.admit(Math.ceil(bytes.length / 2) * 2);
32893
- cidToGid = new Uint16Array(Math.ceil(bytes.length / 2));
32894
- for (let i = 0; i < bytes.length; i += 2)
32895
- cidToGid[i / 2] = bytes[i] << 8 | (bytes[i + 1] ?? 0);
32896
- } else throw new TypeError("Font decoder did not return CID map bytes");
32897
- }
32898
- if (fDesc) {
32899
- const type1Program = yield* resolve(dictGet(fDesc, "FontFile"));
32900
- const program = (yield* resolve(dictGet(fDesc, "FontFile2"))) ?? (yield* resolve(dictGet(fDesc, "FontFile3"))) ?? type1Program;
32901
- if (program?.kind === "stream") {
32902
- const programType = yield* resolve(dictGet(program.dict, "Subtype"));
32903
- const baseEncoding = encNode?.kind === "dict" ? yield* resolve(dictGet(encNode, "BaseEncoding")) : encNode;
32904
- if (program === type1Program) {
32905
- const length1 = yield* resolve(dictGet(program.dict, "Length1"));
32906
- const length2 = yield* resolve(dictGet(program.dict, "Length2"));
32907
- const flags = yield* resolve(dictGet(fDesc, "Flags"));
32908
- const type1Properties = {
32909
- length1: length1?.kind === "number" ? length1.value : 0,
32910
- length2: length2?.kind === "number" ? length2.value : 0,
32911
- flags: flags?.kind === "number" ? flags.value : 0,
32912
- fontMatrix: [1e-3, 0, 0, 1e-3, 0, 0],
32913
- bbox: [0, 0, 0, 0],
32914
- baseEncodingName: baseEncoding?.kind === "name" ? baseEncoding.decoded : void 0,
32915
- differences: glyphNames,
32916
- overridableEncoding: true,
32917
- widths: widths instanceof FontWidths ? widths.createType1View() : {},
32918
- composite: subtype === "Type0",
32919
- cMap: { charCodeOf: (cid) => cid }
32920
- };
32921
- const decoded = yield { kind: "decode", stream: program, purpose: "type1", type1Properties, ...storedEncoding ? { storedEncoding } : {} };
32922
- if (decoded && "storedCff" in decoded) embeddedCff = decoded;
32923
- else if (decoded instanceof Uint8Array) embeddedCff = parseEmbeddedType1Font(decoded, type1Properties, allocationOptions);
32924
- else throw new TypeError("Font decoder did not return a Type1 font");
32925
- } else if (programType?.kind === "name" && (programType.decoded === "Type1C" || programType.decoded === "CIDFontType0C")) {
32926
- const encodingName = baseEncoding?.kind === "name" ? baseEncoding.decoded : void 0;
32927
- const decoded = yield { kind: "decode", stream: program, purpose: "cff", encodingName, differences: glyphNames, ...storedEncoding ? { storedEncoding } : {} };
32928
- if (decoded && "storedCff" in decoded) embeddedCff = decoded;
32929
- else if (decoded instanceof Uint8Array) embeddedCff = parseEmbeddedCffFont(decoded, encodingName, glyphNames, allocationOptions);
32930
- else throw new TypeError("Font decoder did not return a CFF font");
33420
+ const firstCharNode = yield* resolve(dictGet(fObj, "FirstChar"));
33421
+ const widthsArr = yield* resolveArray2(dictGet(fObj, "Widths"), true);
33422
+ if (widthsArr) {
33423
+ const descriptor = yield* resolveDict2(dictGet(fObj, "FontDescriptor"));
33424
+ const missingWidth = descriptor ? yield* resolve(dictGet(descriptor, "MissingWidth")) : void 0;
33425
+ defaultWidth = (missingWidth?.kind === "number" ? missingWidth.value : 0) * type3Scale1000;
33426
+ const firstChar = firstCharNode?.kind === "number" ? firstCharNode.value : 0;
33427
+ const cursor2 = arrayCursor(widthsArr);
33428
+ for (let k = 0; cursor2.remaining; k++) {
33429
+ const wItem = yield* resolve(yield* cursor2.next());
33430
+ if (wItem?.kind === "number") {
33431
+ yield* setWidth(firstChar + k, wItem.value * type3Scale1000);
33432
+ }
33433
+ }
32931
33434
  } else {
32932
- const decoded = yield { kind: "decode", stream: program, purpose: "truetype" };
32933
- if (decoded && "getGlyphId" in decoded) storedTrueType = decoded;
32934
- else if (decoded instanceof Uint8Array) embeddedTrueType = parseTrueTypeFont(decoded, allocationOptions);
32935
- else throw new TypeError("Font decoder did not return a TrueType font");
32936
- if (storedTrueType && subtype !== "Type0" && (storedTrueType.isSymbolicCmap || !storedTrueType.hasCmap)) {
32937
- simpleToGid = /* @__PURE__ */ new Map();
32938
- const encoding = baseEncoding?.kind === "name" ? getEncoding(baseEncoding.decoded) : void 0;
32939
- for (let code = 0; code < 256; code++) {
32940
- let result;
32941
- if (storedTrueType.isSymbolicCmap) {
32942
- result = yield { kind: "truetype-map", font: storedTrueType, code: 61440 + code };
32943
- if (result && "kind" in result && result.kind === "number" && result.value === 0) result = yield { kind: "truetype-map", font: storedTrueType, code };
32944
- } else {
33435
+ const stdMetrics = STANDARD_14_FONTS[normalizeStandard14FontName(baseFont)];
33436
+ defaultWidth = stdMetrics.defaultWidth;
33437
+ if (widths instanceof StoredFontWidths) widths.setDefaults(stdMetrics.widthsByCode);
33438
+ else for (const [codeStr, wVal] of Object.entries(stdMetrics.widthsByCode)) {
33439
+ yield* setWidth(Number(codeStr), wVal);
33440
+ }
33441
+ }
33442
+ }
33443
+ let embeddedCff;
33444
+ let storedTrueType;
33445
+ let embeddedTrueType;
33446
+ let simpleToGid;
33447
+ const fDescDirect = yield* resolveDict2(dictGet(fObj, "FontDescriptor"));
33448
+ const descArrForTt = subtype === "Type0" ? yield* resolveArray2(dictGet(fObj, "DescendantFonts")) : void 0;
33449
+ const cidDictForTt = descArrForTt && descArrForTt.items[0] ? yield* resolveDict2(descArrForTt.items[0]) : void 0;
33450
+ const fDesc = fDescDirect ?? (cidDictForTt ? yield* resolveDict2(dictGet(cidDictForTt, "FontDescriptor")) : void 0);
33451
+ let cidToGid;
33452
+ let storedCidToGid;
33453
+ const cidMap = cidDictForTt ? yield* resolve(dictGet(cidDictForTt, "CIDToGIDMap")) : void 0;
33454
+ if (cidMap?.kind === "stream") {
33455
+ const bytes = yield { kind: "decode", stream: cidMap, purpose: "cid-map" };
33456
+ if (bytes && "byteLength" in bytes && "storage" in bytes) storedCidToGid = bytes;
33457
+ else if (bytes instanceof Uint8Array) {
33458
+ allocation.admit(Math.ceil(bytes.length / 2) * 2);
33459
+ cidToGid = new Uint16Array(Math.ceil(bytes.length / 2));
33460
+ for (let i = 0; i < bytes.length; i += 2)
33461
+ cidToGid[i / 2] = bytes[i] << 8 | (bytes[i + 1] ?? 0);
33462
+ } else throw new TypeError("Font decoder did not return CID map bytes");
33463
+ }
33464
+ if (fDesc) {
33465
+ const type1Program = yield* resolve(dictGet(fDesc, "FontFile"));
33466
+ const program = (yield* resolve(dictGet(fDesc, "FontFile2"))) ?? (yield* resolve(dictGet(fDesc, "FontFile3"))) ?? type1Program;
33467
+ if (program?.kind === "stream") {
33468
+ const programType = yield* resolve(dictGet(program.dict, "Subtype"));
33469
+ const baseEncoding = encNode?.kind === "dict" ? yield* resolve(dictGet(encNode, "BaseEncoding")) : encNode;
33470
+ if (program === type1Program) {
33471
+ const length1 = yield* resolve(dictGet(program.dict, "Length1"));
33472
+ const length2 = yield* resolve(dictGet(program.dict, "Length2"));
33473
+ const flags = yield* resolve(dictGet(fDesc, "Flags"));
33474
+ const type1Properties = {
33475
+ length1: length1?.kind === "number" ? length1.value : 0,
33476
+ length2: length2?.kind === "number" ? length2.value : 0,
33477
+ flags: flags?.kind === "number" ? flags.value : 0,
33478
+ fontMatrix: [1e-3, 0, 0, 1e-3, 0, 0],
33479
+ bbox: [0, 0, 0, 0],
33480
+ baseEncodingName: baseEncoding?.kind === "name" ? baseEncoding.decoded : void 0,
33481
+ differences: glyphNames,
33482
+ overridableEncoding: true,
33483
+ widths: widths instanceof FontWidths ? widths.createType1View() : {},
33484
+ composite: subtype === "Type0",
33485
+ cMap: { charCodeOf: (cid) => cid }
33486
+ };
33487
+ const decoded = yield { kind: "decode", stream: program, purpose: "type1", type1Properties, ...storedEncoding ? { storedEncoding } : {} };
33488
+ if (decoded && "storedCff" in decoded) embeddedCff = decoded;
33489
+ else if (decoded instanceof Uint8Array) embeddedCff = parseEmbeddedType1Font(decoded, type1Properties, allocationOptions);
33490
+ else throw new TypeError("Font decoder did not return a Type1 font");
33491
+ } else if (programType?.kind === "name" && (programType.decoded === "Type1C" || programType.decoded === "CIDFontType0C")) {
33492
+ const encodingName = baseEncoding?.kind === "name" ? baseEncoding.decoded : void 0;
33493
+ const decoded = yield { kind: "decode", stream: program, purpose: "cff", encodingName, differences: glyphNames, ...storedEncoding ? { storedEncoding } : {} };
33494
+ if (decoded && "storedCff" in decoded) embeddedCff = decoded;
33495
+ else if (decoded instanceof Uint8Array) embeddedCff = parseEmbeddedCffFont(decoded, encodingName, glyphNames, allocationOptions);
33496
+ else throw new TypeError("Font decoder did not return a CFF font");
33497
+ } else {
33498
+ const decoded = yield { kind: "decode", stream: program, purpose: "truetype" };
33499
+ if (decoded && "getGlyphId" in decoded) storedTrueType = decoded;
33500
+ else if (decoded instanceof Uint8Array) embeddedTrueType = parseTrueTypeFont(decoded, allocationOptions);
33501
+ else throw new TypeError("Font decoder did not return a TrueType font");
33502
+ if (storedTrueType && subtype !== "Type0" && (storedTrueType.isSymbolicCmap || !storedTrueType.hasCmap)) {
33503
+ simpleToGid = /* @__PURE__ */ new Map();
33504
+ const encoding = baseEncoding?.kind === "name" ? getEncoding(baseEncoding.decoded) : void 0;
33505
+ for (let code = 0; code < 256; code++) {
33506
+ let result;
33507
+ if (storedTrueType.isSymbolicCmap) {
33508
+ result = yield { kind: "truetype-map", font: storedTrueType, code: 61440 + code };
33509
+ if (result && "kind" in result && result.kind === "number" && result.value === 0) result = yield { kind: "truetype-map", font: storedTrueType, code };
33510
+ } else {
33511
+ const name = (yield* glyphName(code)) || encoding?.[code];
33512
+ if (!name) continue;
33513
+ result = yield { kind: "truetype-map", font: storedTrueType, name };
33514
+ }
33515
+ if (!result || !("kind" in result) || result.kind !== "number") throw new TypeError("Expected TrueType glyph ID");
33516
+ if (result.value > 0) simpleToGid.set(code, result.value);
33517
+ }
33518
+ }
33519
+ if (subtype !== "Type0" && embeddedTrueType?.isSymbolicCmap) {
33520
+ simpleToGid = /* @__PURE__ */ new Map();
33521
+ for (let code = 0; code < 256; code++) {
33522
+ const gid = embeddedTrueType.getGlyphId(61440 + code) || embeddedTrueType.getGlyphId(code);
33523
+ if (gid > 0)
33524
+ simpleToGid.set(code, gid);
33525
+ }
33526
+ } else if (subtype !== "Type0" && embeddedTrueType && !embeddedTrueType.hasCmap) {
33527
+ simpleToGid = /* @__PURE__ */ new Map();
33528
+ const encoding = baseEncoding?.kind === "name" ? getEncoding(baseEncoding.decoded) : void 0;
33529
+ for (let code = 0; code < 256; code++) {
32945
33530
  const name = (yield* glyphName(code)) || encoding?.[code];
32946
- if (!name) continue;
32947
- result = yield { kind: "truetype-map", font: storedTrueType, name };
33531
+ const gid = name ? embeddedTrueType.glyphNames.indexOf(name) : -1;
33532
+ if (gid > 0)
33533
+ simpleToGid.set(code, gid);
32948
33534
  }
32949
- if (!result || !("kind" in result) || result.kind !== "number") throw new TypeError("Expected TrueType glyph ID");
32950
- if (result.value > 0) simpleToGid.set(code, result.value);
32951
33535
  }
32952
33536
  }
32953
- if (subtype !== "Type0" && embeddedTrueType?.isSymbolicCmap) {
32954
- simpleToGid = /* @__PURE__ */ new Map();
32955
- for (let code = 0; code < 256; code++) {
32956
- const gid = embeddedTrueType.getGlyphId(61440 + code) || embeddedTrueType.getGlyphId(code);
32957
- if (gid > 0)
32958
- simpleToGid.set(code, gid);
32959
- }
32960
- } else if (subtype !== "Type0" && embeddedTrueType && !embeddedTrueType.hasCmap) {
32961
- simpleToGid = /* @__PURE__ */ new Map();
32962
- const encoding = baseEncoding?.kind === "name" ? getEncoding(baseEncoding.decoded) : void 0;
32963
- for (let code = 0; code < 256; code++) {
32964
- const name = (yield* glyphName(code)) || encoding?.[code];
32965
- const gid = name ? embeddedTrueType.glyphNames.indexOf(name) : -1;
32966
- if (gid > 0)
32967
- simpleToGid.set(code, gid);
32968
- }
33537
+ for (const [code, unicode] of embeddedCff?.unicodeByCode ?? []) {
33538
+ if (!differences.has(code))
33539
+ differences.set(code, unicode);
32969
33540
  }
32970
33541
  }
32971
- for (const [code, unicode] of embeddedCff?.unicodeByCode ?? []) {
32972
- if (!differences.has(code))
32973
- differences.set(code, unicode);
32974
- }
32975
- }
32976
- }
32977
- const standardOutlines = !embeddedTrueType && !storedTrueType && !embeddedCff && subtype !== "Type3" ? getStandardFontOutlines(baseFont, options.onAllocation ? allocationOptions : {}) : void 0;
32978
- for (const [code, unicode] of standardOutlines?.defaultUnicode ?? []) {
32979
- if (!differences.has(code))
32980
- differences.set(code, unicode);
32981
- }
32982
- let encodingCMap;
32983
- let storedEncodingCMap;
32984
- if (subtype === "Type0" && encNode?.kind === "stream") {
32985
- const value = yield { kind: "decode", stream: encNode, purpose: "encoding-cmap" };
32986
- if (value instanceof Uint8Array) encodingCMap = parseCharacterCMap(value, allocationOptions);
32987
- else if (value && "storedCMap" in value) storedEncodingCMap = value;
32988
- else if (value && "lookup" in value) encodingCMap = value;
32989
- else throw new TypeError("Font decoder did not return an encoding CMap");
32990
- }
32991
- fonts.set(fName, {
32992
- name: fName,
32993
- baseFont,
32994
- subtype,
32995
- isTwoByteCid,
32996
- cmap,
32997
- encodingCMap,
32998
- storedCMap,
32999
- storedEncodingCMap,
33000
- differences,
33001
- glyphNames,
33002
- widths,
33003
- defaultWidth,
33004
- fontMatrix,
33005
- charProcs,
33006
- fontResources,
33007
- embeddedTrueType,
33008
- storedTrueType,
33009
- cidToGid,
33010
- storedCidToGid,
33011
- ...storedEncoding ? { storedEncoding } : {},
33012
- simpleToGid,
33013
- embeddedCff,
33014
- standardOutlines
33015
- });
33542
+ }
33543
+ const standardOutlines = !embeddedTrueType && !storedTrueType && !embeddedCff && subtype !== "Type3" ? getStandardFontOutlines(baseFont, options.onAllocation ? allocationOptions : {}) : void 0;
33544
+ for (const [code, unicode] of standardOutlines?.defaultUnicode ?? []) {
33545
+ if (!differences.has(code))
33546
+ differences.set(code, unicode);
33547
+ }
33548
+ let encodingCMap;
33549
+ let storedEncodingCMap;
33550
+ if (subtype === "Type0" && encNode?.kind === "stream") {
33551
+ const value = yield { kind: "decode", stream: encNode, purpose: "encoding-cmap" };
33552
+ if (value instanceof Uint8Array) encodingCMap = parseCharacterCMap(value, allocationOptions);
33553
+ else if (value && "storedCMap" in value) storedEncodingCMap = value;
33554
+ else if (value && "lookup" in value) encodingCMap = value;
33555
+ else throw new TypeError("Font decoder did not return an encoding CMap");
33556
+ }
33557
+ fonts.set(fName, {
33558
+ name: fName,
33559
+ baseFont,
33560
+ subtype,
33561
+ isTwoByteCid,
33562
+ cmap,
33563
+ encodingCMap,
33564
+ storedCMap,
33565
+ storedEncodingCMap,
33566
+ differences,
33567
+ glyphNames,
33568
+ widths,
33569
+ defaultWidth,
33570
+ fontMatrix,
33571
+ charProcs,
33572
+ fontResources,
33573
+ embeddedTrueType,
33574
+ storedTrueType,
33575
+ cidToGid,
33576
+ storedCidToGid,
33577
+ ...storedEncoding ? { storedEncoding } : {},
33578
+ simpleToGid,
33579
+ embeddedCff,
33580
+ standardOutlines
33581
+ });
33582
+ }
33016
33583
  }
33017
33584
  return fonts;
33018
33585
  }
@@ -33023,7 +33590,7 @@ function resolvePageFonts(doc, resourcesDict, selectedName) {
33023
33590
  while (!step.done) {
33024
33591
  let value;
33025
33592
  try {
33026
- if (step.value.kind === "font-encoding" || step.value.kind === "font-label" || step.value.kind === "array-item" || step.value.kind === "truetype-map" || step.value.kind === "font-width-set") throw new TypeError("Stored font requires asynchronous evaluation");
33593
+ if (step.value.kind === "dictionary-entry" || step.value.kind === "font-encoding" || step.value.kind === "font-label" || step.value.kind === "array-item" || step.value.kind === "truetype-map" || step.value.kind === "font-width-set") throw new TypeError("Stored font requires asynchronous evaluation");
33027
33594
  value = step.value.kind === "resolve" ? doc.resolve(step.value.node) : doc.decodeStream(step.value.stream);
33028
33595
  } catch (error) {
33029
33596
  step = steps.throw(error);
@@ -42439,6 +43006,13 @@ function* resolveEvaluationDict(node, arrayPathPrefix) {
42439
43006
  const resolved = yield* resolveEvaluationNode(node, false, arrayPathPrefix);
42440
43007
  return resolved?.kind === "dict" ? resolved : resolved?.kind === "stream" ? resolved.dict : void 0;
42441
43008
  }
43009
+ function* lookupEvaluationDictionary(dict, key) {
43010
+ if (!dict) return void 0;
43011
+ if (!dict.storedEntries) return dictGet(dict, key);
43012
+ const result = yield { kind: "dictionary-value", dict, key };
43013
+ if (!result || !("kind" in result) || result.kind !== "resolved") throw new TypeError("Expected a PDF dictionary value");
43014
+ return result.node;
43015
+ }
42442
43016
  function* resolveEvaluationArray(node, storeRootArray = false, arrayPathPrefix) {
42443
43017
  const resolved = yield* resolveEvaluationNode(node, storeRootArray, arrayPathPrefix);
42444
43018
  return resolved?.kind === "array" ? resolved : void 0;
@@ -43286,8 +43860,8 @@ function* evaluateContentSteps(params) {
43286
43860
  let resolvedMcid = node.mcid;
43287
43861
  let resolvedActualText = node.actualText ?? node.storedActualText;
43288
43862
  if (typeof node.properties === "string" && activeResources) {
43289
- const propsMap = yield* resolveEvaluationDict(dictGet(activeResources, "Properties"));
43290
- const propRefOrNode = propsMap ? dictGet(propsMap, node.properties) : void 0;
43863
+ const propsMap = yield* resolveEvaluationDict(dictGet(activeResources, "Properties"), ["Properties"]);
43864
+ const propRefOrNode = yield* lookupEvaluationDictionary(propsMap, node.properties);
43291
43865
  if (propRefOrNode) {
43292
43866
  const propDict = yield* resolveEvaluationDict(propRefOrNode);
43293
43867
  const propType = propDict ? yield* resolveEvaluationNode(dictGet(propDict, "Type")) : void 0;
@@ -43470,8 +44044,8 @@ function* evaluateContentSteps(params) {
43470
44044
  case "xobject": {
43471
44045
  const st = curState();
43472
44046
  if (activeResources) {
43473
- const xobjDict = yield* resolveEvaluationDict(dictGet(activeResources, "XObject"));
43474
- const xobjNode = xobjDict ? yield* resolveEvaluationNode(dictGet(xobjDict, node.name)) : void 0;
44047
+ const xobjDict = yield* resolveEvaluationDict(dictGet(activeResources, "XObject"), ["XObject"]);
44048
+ const xobjNode = xobjDict ? yield* resolveEvaluationNode(yield* lookupEvaluationDictionary(xobjDict, node.name)) : void 0;
43475
44049
  if (xobjNode?.kind === "stream") {
43476
44050
  if (!(yield* optionalContentVisibilitySteps(dictGet(xobjNode.dict, "OC")))) {
43477
44051
  break;
@@ -43872,7 +44446,7 @@ function* evaluateContentStreamSteps(params) {
43872
44446
  else exhausted = true;
43873
44447
  }
43874
44448
  step = work.next(next.done ? void 0 : next.value);
43875
- } else if (step.value.kind === "dash-array" || step.value.kind === "array-reference" || step.value.kind === "array-item" || step.value.kind === "string-bytes" || step.value.kind === "font-width" || step.value.kind === "font-unicode" || step.value.kind === "cmap-lookup" || step.value.kind === "cmap-character" || step.value.kind === "truetype-number" || step.value.kind === "truetype-path" || step.value.kind === "cid-gid" || step.value.kind === "frame-push" || step.value.kind === "frame-pop" || step.value.kind === "capture-append" || step.value.kind === "transform-path" || step.value.kind === "append-clip" || step.value.kind === "path-append" || step.value.kind === "path-finish") {
44449
+ } else if (step.value.kind === "dictionary-value" || step.value.kind === "dash-array" || step.value.kind === "array-reference" || step.value.kind === "array-item" || step.value.kind === "string-bytes" || step.value.kind === "font-width" || step.value.kind === "font-unicode" || step.value.kind === "cmap-lookup" || step.value.kind === "cmap-character" || step.value.kind === "truetype-number" || step.value.kind === "truetype-path" || step.value.kind === "cid-gid" || step.value.kind === "frame-push" || step.value.kind === "frame-pop" || step.value.kind === "capture-append" || step.value.kind === "transform-path" || step.value.kind === "append-clip" || step.value.kind === "path-append" || step.value.kind === "path-finish") {
43876
44450
  throw new PdfError("E_CAPABILITY", "Stored PDF paths require an asynchronous source driver");
43877
44451
  } else if (step.value.kind === "shading") {
43878
44452
  if (!params.cosDoc) throw new PdfError("E_CAPABILITY", "PDF shading requires a source driver");
@@ -44064,8 +44638,9 @@ function* preparePageAppearanceSteps(pageDict, pageRes, evalResourcesDict, hideA
44064
44638
  const sub = yield* resolveDict3(entry.value, [entry.key.decoded]);
44065
44639
  if (sub) {
44066
44640
  onAllocation?.(64 + sub.entries.length * 64);
44067
- const clonedSub = cosDict({});
44068
- for (const se of sub.entries) dictSet(clonedSub, se.key.decoded, se.value);
44641
+ const shareBacking = entry.key.decoded === "XObject" || entry.key.decoded === "Properties";
44642
+ const clonedSub = sub.storedEntries ? shareBacking ? { ...sub, entries: [] } : yield { kind: "dictionary-merge", destination: sub } : cosDict({});
44643
+ if (!sub.storedEntries) for (const se of sub.entries) dictSet(clonedSub, se.key.decoded, se.value);
44069
44644
  dictSet(evalResourcesDict, entry.key.decoded, clonedSub);
44070
44645
  } else {
44071
44646
  dictSet(evalResourcesDict, entry.key.decoded, entry.value);
@@ -44118,6 +44693,11 @@ function* preparePageAppearanceSteps(pageDict, pageRes, evalResourcesDict, hideA
44118
44693
  dstSub = cosDict({});
44119
44694
  dictSet(evalResourcesDict, subKey, dstSub);
44120
44695
  }
44696
+ if (srcSub.storedEntries || dstSub.storedEntries) {
44697
+ const merged = yield { kind: "dictionary-merge", destination: dstSub, source: srcSub };
44698
+ dictSet(evalResourcesDict, subKey, merged);
44699
+ continue;
44700
+ }
44121
44701
  for (const se of srcSub.entries) {
44122
44702
  if (!dictGet(dstSub, se.key.decoded)) {
44123
44703
  onAllocation?.(64);
@@ -45870,7 +46450,7 @@ var PdfPage = class {
45870
46450
  const request = step.value;
45871
46451
  if (request.kind === "resolve" || request.kind === "catalog") {
45872
46452
  step = work.next(this.cosDoc.resolve(request.kind === "catalog" ? this.cosDoc.rootRef : request.node));
45873
- } else if (request.kind === "array-reference" || request.kind === "array-item") throw new TypeError("Stored visibility requires asynchronous evaluation");
46453
+ } else if (request.kind === "dictionary-merge" || request.kind === "array-reference" || request.kind === "array-item") throw new TypeError("Stored visibility requires asynchronous evaluation");
45874
46454
  else if (request.kind === "appearance-content") {
45875
46455
  appearance = parseContentStream(this.cosDoc.decodeStream(request.stream));
45876
46456
  step = work.next(appearance.length > 0);
@@ -48147,7 +48727,7 @@ async function renderRetainedPagePixels(page2, storage, options = {}) {
48147
48727
  }
48148
48728
 
48149
48729
  // packages/pdf-ast/src/cos/range-parser.ts
48150
- import { listenForAbort } from "@poe-platform/safe-fs/contracts";
48730
+ import { listenForAbort as listenForAbort2 } from "@poe-platform/safe-fs/contracts";
48151
48731
  function limit(value, name) {
48152
48732
  const result = value ?? Infinity;
48153
48733
  if (result !== Infinity && (!Number.isSafeInteger(result) || result < 0)) throw new RangeError(`Invalid ${name}`);
@@ -48199,7 +48779,7 @@ async function resolveStreamLength(entry, options) {
48199
48779
  let dispose = () => {
48200
48780
  };
48201
48781
  const cancelled = new Promise((ignored, reject) => {
48202
- dispose = listenForAbort(signal, () => reject(signal.reason));
48782
+ dispose = listenForAbort2(signal, () => reject(signal.reason));
48203
48783
  });
48204
48784
  const pending = Promise.resolve().then(() => {
48205
48785
  signal.throwIfAborted();
@@ -48222,10 +48802,10 @@ async function readValue(lexer, depth, nodes, options) {
48222
48802
  while (!step.done) {
48223
48803
  signal?.throwIfAborted();
48224
48804
  const request = step.value;
48225
- if (request && request !== "token" && request.kind === "array-append") {
48805
+ if (request && request !== "token" && (request.kind === "array-append" || request.kind === "dictionary-append")) {
48226
48806
  let position;
48227
48807
  try {
48228
- position = await appendStoredRecord(options.arrayStorage, request.node, request.previous, signal);
48808
+ position = await appendStoredRecord(request.kind === "array-append" ? options.arrayStorage : options.dictionaryStorage, request.kind === "array-append" ? request.node : request.entry, request.previous, signal);
48229
48809
  } catch (error) {
48230
48810
  options.onBackingError?.(error);
48231
48811
  throw error;
@@ -48255,7 +48835,7 @@ async function parseCosRangeValue(source, offset, options = {}) {
48255
48835
  const depth = limit(options.maxRecursionDepth, "maxRecursionDepth");
48256
48836
  const nodes = limit(options.maxNodes, "maxNodes");
48257
48837
  const maxTokenBytes = limit(options.maxTokenBytes, "maxTokenBytes");
48258
- const lexer = new CosRangeLexer(source, { ...options.onBackingError ? { onBackingError: options.onBackingError } : {}, start: offset, ...options.end === void 0 ? {} : { end: options.end }, maxTokenBytes, ...options.signal ? { signal: options.signal } : {} });
48838
+ const lexer = new CosRangeLexer(source, { compactNumbers: options.compactNumbers ?? false, compactKeywords: options.compactKeywords ?? false, ...options.onBackingError ? { onBackingError: options.onBackingError } : {}, start: offset, ...options.end === void 0 ? {} : { end: options.end }, maxTokenBytes, ...options.signal ? { signal: options.signal } : {} });
48259
48839
  return { value: await readValue(lexer, depth, nodes, options), offset: lexer.offset };
48260
48840
  }
48261
48841
  async function parseCosRangeObject(source, offset, options = {}) {
@@ -48264,7 +48844,7 @@ async function parseCosRangeObject(source, offset, options = {}) {
48264
48844
  const tokenBytes = limit(options.maxTokenBytes, "maxTokenBytes");
48265
48845
  const { signal } = options;
48266
48846
  signal?.throwIfAborted();
48267
- const lexer = new CosRangeLexer(source, { ...options.onBackingError ? { onBackingError: options.onBackingError } : {}, start: offset, maxTokenBytes: tokenBytes, ...signal ? { signal } : {} });
48847
+ const lexer = new CosRangeLexer(source, { compactNumbers: options.compactNumbers ?? false, compactKeywords: options.compactKeywords ?? false, ...options.onBackingError ? { onBackingError: options.onBackingError } : {}, start: offset, maxTokenBytes: tokenBytes, ...signal ? { signal } : {} });
48268
48848
  const object = await lexer.nextToken();
48269
48849
  const generation = await lexer.nextToken();
48270
48850
  const keyword = await lexer.nextToken();
@@ -48373,7 +48953,7 @@ async function* scanCosRangeObjects(source, options = {}) {
48373
48953
 
48374
48954
  // packages/pdf-ast/src/cos/range-xref.ts
48375
48955
  import { readBytes as readBytes12 } from "@poe-platform/safe-fs/contracts";
48376
- function budget(value, name) {
48956
+ function budget2(value, name) {
48377
48957
  if (value === void 0 || value === Infinity) return Infinity;
48378
48958
  if (!Number.isSafeInteger(value) || value < 0) throw new RangeError(`Invalid ${name}`);
48379
48959
  return value;
@@ -48432,12 +49012,12 @@ var DecodedFields = class {
48432
49012
  }
48433
49013
  };
48434
49014
  async function* readCosXrefRevision(source, offset, options = {}) {
48435
- const maximum10 = budget(options.maxEntries, "maxEntries");
48436
- const maxDecoded = budget(options.maxDecodedBytes, "maxDecodedBytes");
49015
+ const maximum10 = budget2(options.maxEntries, "maxEntries");
49016
+ const maxDecoded = budget2(options.maxDecodedBytes, "maxDecodedBytes");
48437
49017
  const { signal } = options;
48438
49018
  signal?.throwIfAborted();
48439
49019
  if (!Number.isSafeInteger(offset) || offset < 0 || offset >= source.size) throw new PdfError("E_PARSE", `Invalid xref offset: ${offset}`);
48440
- const lexer = new CosRangeLexer(source, { start: offset, ...signal ? { signal } : {}, ...options.maxTokenBytes === void 0 ? {} : { maxTokenBytes: options.maxTokenBytes } });
49020
+ const lexer = new CosRangeLexer(source, { compactNumbers: options.compactNumbers ?? false, compactKeywords: options.compactKeywords ?? false, start: offset, ...signal ? { signal } : {}, ...options.maxTokenBytes === void 0 ? {} : { maxTokenBytes: options.maxTokenBytes } });
48441
49021
  const first = await lexer.nextToken();
48442
49022
  let admitted = 0;
48443
49023
  const admit2 = (count) => {
@@ -48552,271 +49132,6 @@ async function* readCosXrefRevision(source, offset, options = {}) {
48552
49132
  }
48553
49133
  }
48554
49134
 
48555
- // packages/pdf-ast/src/cos/object-index.ts
48556
- import { listenForAbort as listenForAbort2 } from "@poe-platform/safe-fs/contracts";
48557
- var recordBytes = 32;
48558
- function integer(value, name) {
48559
- if (!Number.isSafeInteger(value) || value < 0) throw new RangeError(`Invalid ${name}`);
48560
- return value;
48561
- }
48562
- function budget2(value, name) {
48563
- return value === void 0 || value === Infinity ? Infinity : integer(value, name);
48564
- }
48565
- function fields(entry) {
48566
- const key = integer(entry.objectNumber, "PDF object number");
48567
- if (entry.type === "free") return [key, integer(entry.nextFreeObjectNumber ?? 0, "free object number"), integer(entry.generationNumber ?? 0, "generation number"), 0];
48568
- if (entry.type === "uncompressed") return [key, integer(entry.offset, "object offset"), integer(entry.generationNumber ?? 0, "generation number"), 1];
48569
- if (entry.type === "compressed") return [key, integer(entry.objectStreamNumber, "object stream number"), integer(entry.indexInStream ?? entry.indexInObjectStream, "object stream index"), 2];
48570
- throw new PdfError("E_PARSE", "Invalid PDF cross-reference entry type");
48571
- }
48572
- function decode(bytes, offset = 0) {
48573
- const view = new DataView(bytes.buffer, bytes.byteOffset + offset, recordBytes);
48574
- const objectNumber = view.getFloat64(0);
48575
- const first = view.getFloat64(8);
48576
- const second = view.getFloat64(16);
48577
- const type = view.getFloat64(24);
48578
- if (type === 0) return { objectNumber, type: "free", nextFreeObjectNumber: first, generationNumber: second };
48579
- if (type === 1) return { objectNumber, type: "uncompressed", offset: first, generationNumber: second };
48580
- if (type === 2) return { objectNumber, type: "compressed", objectStreamNumber: first, indexInStream: second };
48581
- throw new PdfError("E_PARSE", "Invalid staged PDF index record");
48582
- }
48583
- async function* encode2(entries, chunkBytes) {
48584
- let bytes = new Uint8Array(chunkBytes);
48585
- let offset = 0;
48586
- for await (const entry of entries) {
48587
- const view = new DataView(bytes.buffer, offset, recordBytes);
48588
- const values = fields(entry);
48589
- for (let i = 0; i < values.length; i++) view.setFloat64(i * 8, values[i]);
48590
- offset += recordBytes;
48591
- if (offset === bytes.length) {
48592
- yield bytes;
48593
- bytes = new Uint8Array(chunkBytes);
48594
- offset = 0;
48595
- }
48596
- }
48597
- if (offset) yield bytes.subarray(0, offset);
48598
- }
48599
- async function* records(source, signal) {
48600
- for await (const bytes of source.stream(0, source.size, signal)) {
48601
- if (bytes.length % recordBytes !== 0) throw new PdfError("E_PARSE", "Truncated staged PDF index");
48602
- for (let offset = 0; offset < bytes.length; offset += recordBytes) {
48603
- signal?.throwIfAborted();
48604
- yield decode(bytes, offset);
48605
- }
48606
- }
48607
- }
48608
- async function* merge(first, second, duplicate, signal) {
48609
- const left = records(first, signal);
48610
- const right = records(second, signal);
48611
- try {
48612
- let a = await left.next();
48613
- let b = await right.next();
48614
- let turns = 0;
48615
- while (!a.done || !b.done) {
48616
- signal?.throwIfAborted();
48617
- if (!a.done && (b.done || a.value.objectNumber <= b.value.objectNumber)) {
48618
- const equal2 = !b.done && a.value.objectNumber === b.value.objectNumber;
48619
- yield equal2 && duplicate === "last" && !b.done ? b.value : a.value;
48620
- if (equal2) b = await right.next();
48621
- a = await left.next();
48622
- } else if (!b.done) {
48623
- yield b.value;
48624
- b = await right.next();
48625
- }
48626
- if (++turns % 1024 === 0) await new Promise((resolve2) => setTimeout(resolve2, 0));
48627
- }
48628
- } finally {
48629
- await left.return(void 0);
48630
- await right.return(void 0);
48631
- }
48632
- }
48633
- var PdfObjectIndex = class _PdfObjectIndex {
48634
- constructor(source, signal) {
48635
- this.source = source;
48636
- this.signal = signal;
48637
- }
48638
- source;
48639
- signal;
48640
- closing;
48641
- get size() {
48642
- return this.source.size / recordBytes;
48643
- }
48644
- static async build(input, storage, options = {}) {
48645
- const duplicate = options.duplicate ?? "first";
48646
- if (duplicate !== "first" && duplicate !== "last") throw new RangeError("Invalid PDF index duplicate policy");
48647
- const runEntries = integer(options.runEntries ?? 2048, "runEntries");
48648
- const chunkBytes = integer(options.chunkBytes ?? 64 * 1024, "chunkBytes");
48649
- const cacheBytes = integer(options.cacheBytes ?? 256 * 1024, "cacheBytes");
48650
- if (!runEntries || chunkBytes < recordBytes || chunkBytes % recordBytes !== 0 || cacheBytes < chunkBytes) throw new RangeError("Invalid PDF index batch/cache sizes");
48651
- const maxEntries = budget2(options.maxEntries, "maxEntries");
48652
- const maxStagingBytes = budget2(options.maxStagingBytes, "maxStagingBytes");
48653
- const { signal } = options;
48654
- signal?.throwIfAborted();
48655
- const owned = /* @__PURE__ */ new Set();
48656
- const levels = [];
48657
- let stagedBytes = 0;
48658
- let admitted = 0;
48659
- let batch = [];
48660
- const dispose = async (source) => {
48661
- try {
48662
- await source.close();
48663
- } finally {
48664
- owned.delete(source);
48665
- stagedBytes -= source.size;
48666
- }
48667
- };
48668
- const stage = async (entries) => {
48669
- let reserved = 0;
48670
- async function* chunks() {
48671
- for await (const bytes of encode2(entries, chunkBytes)) {
48672
- signal?.throwIfAborted();
48673
- if (bytes.length > Math.min(maxStagingBytes, Number.MAX_SAFE_INTEGER) - stagedBytes) throw new PdfError("E_LIMIT", "PDF index staging byte limit exceeded");
48674
- stagedBytes += bytes.length;
48675
- reserved += bytes.length;
48676
- yield bytes;
48677
- }
48678
- }
48679
- try {
48680
- const source = await PdfFileSource.fromStream(storage.fs, storage.directory, chunks(), { chunkBytes, cacheBytes, ...signal ? { signal } : {} });
48681
- owned.add(source);
48682
- return source;
48683
- } catch (error) {
48684
- stagedBytes -= reserved;
48685
- throw error;
48686
- }
48687
- };
48688
- const flush = async () => {
48689
- if (duplicate === "last") batch.reverse();
48690
- batch.sort((a, b) => a.objectNumber - b.objectNumber);
48691
- const sorted = batch;
48692
- batch = [];
48693
- function* unique() {
48694
- let previous = -1;
48695
- for (const entry of sorted) if (entry.objectNumber !== previous) {
48696
- previous = entry.objectNumber;
48697
- yield entry;
48698
- }
48699
- }
48700
- let run = await stage(unique());
48701
- let level = 0;
48702
- while (levels[level]) {
48703
- const earlier = levels[level];
48704
- const combined = await stage(merge(earlier, run, duplicate, signal));
48705
- await dispose(earlier);
48706
- await dispose(run);
48707
- levels[level++] = void 0;
48708
- run = combined;
48709
- }
48710
- levels[level] = run;
48711
- };
48712
- const iterator = Symbol.asyncIterator in input ? input[Symbol.asyncIterator]() : input[Symbol.iterator]();
48713
- let ended = false;
48714
- const next = async () => {
48715
- signal?.throwIfAborted();
48716
- if (!signal) return iterator.next();
48717
- let dispose2 = () => {
48718
- };
48719
- const cancelled = new Promise((ignored, reject) => {
48720
- dispose2 = listenForAbort2(signal, () => reject(signal.reason));
48721
- });
48722
- const pending = Promise.resolve().then(() => {
48723
- signal.throwIfAborted();
48724
- return iterator.next();
48725
- });
48726
- try {
48727
- return await Promise.race([pending, cancelled]);
48728
- } finally {
48729
- dispose2();
48730
- }
48731
- };
48732
- try {
48733
- while (true) {
48734
- const step = await next();
48735
- signal?.throwIfAborted();
48736
- if (step.done) {
48737
- ended = true;
48738
- break;
48739
- }
48740
- if (admitted >= Math.min(maxEntries, Number.MAX_SAFE_INTEGER)) throw new PdfError("E_LIMIT", "PDF index entry limit exceeded");
48741
- admitted++;
48742
- const values = fields(step.value);
48743
- const entry = step.value.type === "compressed" ? { objectNumber: values[0], type: "compressed", objectStreamNumber: values[1], indexInStream: values[2] } : step.value.type === "free" ? { objectNumber: values[0], type: "free", nextFreeObjectNumber: values[1], generationNumber: values[2] } : { objectNumber: values[0], type: "uncompressed", offset: values[1], generationNumber: values[2] };
48744
- batch.push(entry);
48745
- if (batch.length === runEntries) await flush();
48746
- if (admitted % 1024 === 0) await new Promise((resolve2) => setTimeout(resolve2, 0));
48747
- }
48748
- if (batch.length) await flush();
48749
- let result;
48750
- for (let level = levels.length - 1; level >= 0; level--) {
48751
- const run = levels[level];
48752
- if (!run) continue;
48753
- if (!result) result = run;
48754
- else {
48755
- const combined = await stage(merge(result, run, duplicate, signal));
48756
- await dispose(result);
48757
- await dispose(run);
48758
- result = combined;
48759
- }
48760
- }
48761
- result ??= await stage([]);
48762
- signal?.throwIfAborted();
48763
- owned.delete(result);
48764
- return new _PdfObjectIndex(result, signal);
48765
- } catch (error) {
48766
- for (const source of owned) {
48767
- try {
48768
- await source.close();
48769
- } catch {
48770
- }
48771
- }
48772
- throw error;
48773
- } finally {
48774
- if (!ended) {
48775
- try {
48776
- const returning = iterator.return?.();
48777
- if (returning) {
48778
- if (signal?.aborted) void Promise.resolve(returning).catch(() => {
48779
- });
48780
- else await returning;
48781
- }
48782
- } catch {
48783
- }
48784
- }
48785
- }
48786
- }
48787
- async get(objectNumber, signal) {
48788
- integer(objectNumber, "PDF object number");
48789
- this.assertOpen(signal);
48790
- let low = 0;
48791
- let high = this.size;
48792
- while (low < high) {
48793
- const middle = low + Math.floor((high - low) / 2);
48794
- const entry = decode(await this.source.read(middle * recordBytes, recordBytes, signal));
48795
- this.assertOpen(signal);
48796
- if (entry.objectNumber === objectNumber) return entry;
48797
- if (entry.objectNumber < objectNumber) low = middle + 1;
48798
- else high = middle;
48799
- }
48800
- return void 0;
48801
- }
48802
- assertOpen(signal) {
48803
- this.signal?.throwIfAborted();
48804
- signal?.throwIfAborted();
48805
- if (this.closing) throw new PdfError("E_CAPABILITY", "PDF object index is closed");
48806
- }
48807
- async *entries(signal) {
48808
- this.assertOpen(signal);
48809
- for await (const entry of records(this.source, signal)) {
48810
- this.assertOpen(signal);
48811
- yield entry;
48812
- }
48813
- }
48814
- close() {
48815
- this.closing ??= this.source.close();
48816
- return this.closing;
48817
- }
48818
- };
48819
-
48820
49135
  // packages/pdf-ast/src/cos/cross-reference.ts
48821
49136
  var marker = new TextEncoder().encode("startxref");
48822
49137
  async function header(source, signal) {
@@ -48851,6 +49166,8 @@ async function findPdfStartXref(source, options = {}) {
48851
49166
  if (!matched) continue;
48852
49167
  const lexer = new CosRangeLexer(source, {
48853
49168
  start: start + i + marker.length,
49169
+ compactNumbers: options.compactNumbers ?? false,
49170
+ compactKeywords: options.compactKeywords ?? false,
48854
49171
  ...options.maxTokenBytes === void 0 ? {} : { maxTokenBytes: options.maxTokenBytes },
48855
49172
  ...options.signal ? { signal: options.signal } : {}
48856
49173
  });
@@ -48974,39 +49291,6 @@ async function openPdfCrossReference(source, storage, options = {}) {
48974
49291
  }
48975
49292
  }
48976
49293
 
48977
- // packages/pdf-ast/src/cos/filter-dictionary.ts
48978
- async function resolvePdfStreamDictionary(dict, lookup, active, options) {
48979
- let remaining = options.maxNodes ?? 65536;
48980
- const resolve2 = async (node, depth) => {
48981
- if (--remaining < 0 || depth >= (options.maxRecursionDepth ?? 100)) throw new PdfError("E_LIMIT", "PDF filter resolution limit exceeded");
48982
- if (node.kind === "ref") {
48983
- if (active.has(node.objectNumber)) throw new PdfError("E_PARSE", "PDF filter reference cycle");
48984
- const object = await lookup(node);
48985
- if (!object) throw new PdfError("E_PARSE", "Missing PDF filter reference");
48986
- active.add(node.objectNumber);
48987
- try {
48988
- return await resolve2(object.value, depth + 1);
48989
- } finally {
48990
- active.delete(node.objectNumber);
48991
- }
48992
- }
48993
- if (node.kind === "array") {
48994
- const items = [];
48995
- for (const item of node.items) items.push(await resolve2(item, depth + 1));
48996
- return { ...node, items };
48997
- }
48998
- if (node.kind === "dict") {
48999
- const entries2 = [];
49000
- for (const entry of node.entries) entries2.push({ ...entry, value: await resolve2(entry.value, depth + 1) });
49001
- return { ...node, entries: entries2 };
49002
- }
49003
- return node;
49004
- };
49005
- const entries = [];
49006
- for (const entry of dict.entries) entries.push(["Filter", "F", "DecodeParms", "DP", "Type"].includes(entry.key.decoded) ? { ...entry, value: await resolve2(entry.value, 0) } : entry);
49007
- return { ...dict, entries };
49008
- }
49009
-
49010
49294
  // packages/pdf-ast/src/cos/reference-set.ts
49011
49295
  var PdfReferenceSet = class {
49012
49296
  constructor(storage, maximum10 = Infinity, signal) {
@@ -49021,12 +49305,16 @@ var PdfReferenceSet = class {
49021
49305
  tail = /* @__PURE__ */ new Set();
49022
49306
  levels = [];
49023
49307
  closed = false;
49024
- async add(number) {
49308
+ async has(number) {
49025
49309
  if (this.closed) throw new PdfError("E_CAPABILITY", "PDF reference set is closed");
49026
49310
  this.signal?.throwIfAborted();
49027
49311
  if (!Number.isSafeInteger(number) || number < 0) throw new RangeError("Invalid PDF reference number");
49028
- if (this.tail.has(number)) return false;
49029
- for (const level2 of this.levels) if (await level2?.get(number, this.signal)) return false;
49312
+ if (this.tail.has(number)) return true;
49313
+ for (const level of this.levels) if (await level?.get(number, this.signal)) return true;
49314
+ return false;
49315
+ }
49316
+ async add(number) {
49317
+ if (await this.has(number)) return false;
49030
49318
  this.tail.add(number);
49031
49319
  if (this.tail.size < 64) return true;
49032
49320
  let level = 0;
@@ -49074,6 +49362,54 @@ var PdfReferenceSet = class {
49074
49362
  }
49075
49363
  };
49076
49364
 
49365
+ // packages/pdf-ast/src/cos/filter-dictionary.ts
49366
+ async function resolvePdfStreamDictionary(dict, lookup, active, options) {
49367
+ let remaining = options.maxNodes ?? 65536;
49368
+ const resolve2 = async (node, depth) => {
49369
+ if (--remaining < 0 || depth >= (options.maxRecursionDepth ?? 100)) throw new PdfError("E_LIMIT", "PDF filter resolution limit exceeded");
49370
+ if (node.kind === "ref") {
49371
+ if (active.has(node.objectNumber)) throw new PdfError("E_PARSE", "PDF filter reference cycle");
49372
+ const object = await lookup(node);
49373
+ if (!object) throw new PdfError("E_PARSE", "Missing PDF filter reference");
49374
+ active.add(node.objectNumber);
49375
+ try {
49376
+ return await resolve2(object.value, depth + 1);
49377
+ } finally {
49378
+ active.delete(node.objectNumber);
49379
+ }
49380
+ }
49381
+ if (node.kind === "array") {
49382
+ const items = [];
49383
+ const { storedItems, ...ordinary } = node;
49384
+ if (storedItems) {
49385
+ const reader = readStoredItems(storedItems, options.signal);
49386
+ try {
49387
+ for (; ; ) {
49388
+ const item = await reader.next().catch((error) => {
49389
+ options.onBackingError?.(error);
49390
+ throw error;
49391
+ });
49392
+ if (item.done) break;
49393
+ items.push(await resolve2(item.value, depth + 1));
49394
+ }
49395
+ } finally {
49396
+ await reader.return();
49397
+ }
49398
+ } else for (const item of node.items) items.push(await resolve2(item, depth + 1));
49399
+ return { ...ordinary, items };
49400
+ }
49401
+ if (node.kind === "dict") {
49402
+ const entries2 = [];
49403
+ for (const entry of node.entries) entries2.push({ ...entry, value: await resolve2(entry.value, depth + 1) });
49404
+ return { ...node, entries: entries2 };
49405
+ }
49406
+ return node;
49407
+ };
49408
+ const entries = [];
49409
+ for (const entry of dict.entries) entries.push(["Filter", "F", "DecodeParms", "DP", "Type"].includes(entry.key.decoded) ? { ...entry, value: await resolve2(entry.value, 0) } : entry);
49410
+ return { ...dict, entries };
49411
+ }
49412
+
49077
49413
  // packages/pdf-ast/src/cos/recovered-reference.ts
49078
49414
  async function* recoveredBodies(source, index2, storage, options) {
49079
49415
  const visited = new PdfReferenceSet(storage, options.index?.maxStagingBytes, options.signal);
@@ -49203,6 +49539,7 @@ var PdfObjectReader = class {
49203
49539
  this.capacity = integer2(options.objectStreamCacheEntries ?? 2, "objectStreamCacheEntries", 1);
49204
49540
  this.stagingLimit = maximum2(options.maxStagingBytes, "maxStagingBytes");
49205
49541
  maximum2(options.maxObjectStreamMembers, "maxObjectStreamMembers");
49542
+ maximum2(options.maxTraversalStagingBytes, "maxTraversalStagingBytes");
49206
49543
  this.options = {
49207
49544
  maxNodes: 65536,
49208
49545
  maxTokenBytes: 1048576,
@@ -49216,6 +49553,10 @@ var PdfObjectReader = class {
49216
49553
  index;
49217
49554
  storage;
49218
49555
  streams = /* @__PURE__ */ new Map();
49556
+ // Recursive length/object-stream lookups share one failure identity so an
49557
+ // outer recovery pass cannot mistake a caller-storage error for PDF syntax.
49558
+ backingFailures = /* @__PURE__ */ new WeakMap();
49559
+ lengthPaths = /* @__PURE__ */ new WeakMap();
49219
49560
  repairedOffsets = /* @__PURE__ */ new Map();
49220
49561
  options;
49221
49562
  capacity;
@@ -49245,7 +49586,10 @@ var PdfObjectReader = class {
49245
49586
  const object2 = await this.load(objectNumber, generationNumber, /* @__PURE__ */ new Set());
49246
49587
  if (object2?.value.kind !== "dict" || !object2.stream) throw new PdfError("E_PARSE", "Expected an indexed PDF stream");
49247
49588
  const active = /* @__PURE__ */ new Set([objectNumber]);
49248
- return { object: object2, dict: await resolvePdfStreamDictionary(object2.value, (ref) => this.load(ref.objectNumber, ref.generationNumber, active), active, this.options) };
49589
+ return { object: object2, dict: await resolvePdfStreamDictionary(object2.value, (ref) => this.load(ref.objectNumber, ref.generationNumber, active), active, { ...this.options, onBackingError: (error) => {
49590
+ this.backingFailures.set(active, { error });
49591
+ this.options.onBackingError?.(error);
49592
+ } }) };
49249
49593
  });
49250
49594
  const span = object.stream;
49251
49595
  const input = () => this.source.stream(span.start, span.end - span.start, this.options.signal);
@@ -49253,13 +49597,83 @@ var PdfObjectReader = class {
49253
49597
  const decodeOptions = { ...this.options, stopBeforeImageCodec: options.stopBeforeImageCodec ?? false, raw: options.raw ?? false };
49254
49598
  yield* security ? decodePdfEncryptedStreamChunks(security, objectNumber, generationNumber, dict, input, decodeOptions) : decodePdfStreamChunks(dict, input, decodeOptions);
49255
49599
  }
49256
- async load(objectNumber, generationNumber, active, arrays = {}) {
49600
+ /** A stream-valued /Length is invalid as a length, but its references still
49601
+ * need cycle, admission and backing-error validation. Walk those discarded
49602
+ * values in source order instead of retaining one parser and AST per link. */
49603
+ async resolveLength(reference, active) {
49604
+ const path = {
49605
+ seen: new PdfReferenceSet(this.storage, this.options.maxTraversalStagingBytes, this.options.signal),
49606
+ parent: this.lengthPaths.get(active),
49607
+ depth: 0
49608
+ };
49609
+ this.lengthPaths.set(active, path);
49610
+ let next = reference, result, failed = false;
49611
+ try {
49612
+ while (next) {
49613
+ const current = next;
49614
+ next = void 0;
49615
+ const object = await this.load(
49616
+ current.objectNumber,
49617
+ current.generationNumber,
49618
+ active,
49619
+ this.options.valueArrays ?? {},
49620
+ async (child) => {
49621
+ next = child;
49622
+ return void 0;
49623
+ }
49624
+ );
49625
+ if (path.depth === 0 && object?.value.kind === "number") result = object.value.value;
49626
+ try {
49627
+ await path.seen.add(current.objectNumber);
49628
+ } catch (error) {
49629
+ this.backingFailures.set(active, { error });
49630
+ this.options.onBackingError?.(error);
49631
+ throw error;
49632
+ }
49633
+ path.depth++;
49634
+ }
49635
+ return result;
49636
+ } catch (error) {
49637
+ failed = true;
49638
+ throw error;
49639
+ } finally {
49640
+ if (path.parent) this.lengthPaths.set(active, path.parent);
49641
+ else this.lengthPaths.delete(active);
49642
+ try {
49643
+ await path.seen.close();
49644
+ } catch (error) {
49645
+ if (!failed) {
49646
+ this.backingFailures.set(active, { error });
49647
+ this.options.onBackingError?.(error);
49648
+ await Promise.reject(error);
49649
+ }
49650
+ }
49651
+ }
49652
+ }
49653
+ async load(objectNumber, generationNumber, active, arrays = this.options.valueArrays ?? {}, resolveLength) {
49257
49654
  this.options.signal?.throwIfAborted();
49258
49655
  if (active.has(objectNumber)) throw new PdfError("E_PARSE", "PDF indirect object cycle");
49259
- if (active.size >= this.options.maxRecursionDepth) throw new PdfError("E_LIMIT", "PDF object resolution depth limit exceeded");
49656
+ let depth = active.size;
49657
+ for (let path = this.lengthPaths.get(active); path; path = path.parent) {
49658
+ let seen;
49659
+ try {
49660
+ seen = await path.seen.has(objectNumber);
49661
+ } catch (error) {
49662
+ this.backingFailures.set(active, { error });
49663
+ this.options.onBackingError?.(error);
49664
+ throw error;
49665
+ }
49666
+ if (seen) throw new PdfError("E_PARSE", "PDF indirect object cycle");
49667
+ depth += path.depth;
49668
+ }
49669
+ if (depth >= this.options.maxRecursionDepth) throw new PdfError("E_LIMIT", "PDF object resolution depth limit exceeded");
49260
49670
  const entry = await this.index.get(objectNumber, this.options.signal);
49261
49671
  if (!entry || entry.type === "free" || generationNumber !== (entry.generationNumber ?? 0)) return void 0;
49262
49672
  active.add(objectNumber);
49673
+ const onBackingError = (error) => {
49674
+ this.backingFailures.set(active, { error });
49675
+ this.options.onBackingError?.(error);
49676
+ };
49263
49677
  try {
49264
49678
  if (entry.type === "compressed") {
49265
49679
  const container = entry.objectStreamNumber;
@@ -49272,32 +49686,29 @@ var PdfObjectReader = class {
49272
49686
  if (row.number !== objectNumber) throw new PdfError("E_PARSE", "Compressed object identity does not match xref");
49273
49687
  const end = ordinal + 1 === stream.count ? stream.data.size : stream.first + (await this.headerRow(stream.header, ordinal + 1)).offset;
49274
49688
  const start = stream.first + row.offset;
49275
- const parsed = await parseCosRangeValue(stream.data, start, { ...this.options, ...arrays, end });
49689
+ const parsed = await parseCosRangeValue(stream.data, start, { ...this.options, ...arrays, end, onBackingError });
49276
49690
  if (!parsed.value) throw new PdfError("E_PARSE", "Empty compressed object");
49277
49691
  return { objectNumber, generationNumber, value: parsed.value, span: { start, end: parsed.offset } };
49278
49692
  }
49279
49693
  let object;
49280
- let backingFailure;
49281
- const onBackingError = (error) => {
49282
- backingFailure = { error };
49283
- };
49694
+ let pendingLength;
49284
49695
  try {
49285
49696
  object = await parseCosRangeObject(this.source, this.repairedOffsets.get(objectNumber) ?? entry.offset, {
49286
49697
  ...this.options,
49287
49698
  ...arrays,
49288
49699
  onBackingError,
49289
- resolveLength: async (reference) => {
49290
- const resolved = await this.load(reference.objectNumber, reference.generationNumber, active);
49291
- return resolved?.value.kind === "number" ? resolved.value.value : void 0;
49292
- }
49700
+ resolveLength: (reference) => pendingLength = resolveLength ? resolveLength(reference) : this.resolveLength(reference, active)
49293
49701
  });
49294
49702
  if (object.objectNumber !== objectNumber || object.generationNumber !== generationNumber) throw new PdfError("E_PARSE", "Indirect object identity does not match xref");
49295
49703
  } catch (error) {
49704
+ await pendingLength?.catch(() => {
49705
+ });
49296
49706
  this.options.signal?.throwIfAborted();
49707
+ const backingFailure = this.backingFailures.get(active);
49297
49708
  if (backingFailure && Object.is(backingFailure.error, error)) throw error;
49298
49709
  if (this.options.recovery !== "repair" || !(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
49299
49710
  let recovered;
49300
- for await (const event of scanCosRangeObjects(this.source, { ...this.options, ...arrays })) {
49711
+ for await (const event of scanCosRangeObjects(this.source, { ...this.options, ...arrays, onBackingError })) {
49301
49712
  if (event.kind === "object" && event.object.objectNumber === objectNumber && event.object.generationNumber === generationNumber) recovered = event.object;
49302
49713
  }
49303
49714
  if (!recovered) throw error;
@@ -49363,7 +49774,10 @@ var PdfObjectReader = class {
49363
49774
  active.add(number);
49364
49775
  let dict;
49365
49776
  try {
49366
- dict = await resolvePdfStreamDictionary(object.value, (ref) => this.load(ref.objectNumber, ref.generationNumber, active), active, this.options);
49777
+ dict = await resolvePdfStreamDictionary(object.value, (ref) => this.load(ref.objectNumber, ref.generationNumber, active), active, { ...this.options, onBackingError: (error) => {
49778
+ this.backingFailures.set(active, { error });
49779
+ this.options.onBackingError?.(error);
49780
+ } });
49367
49781
  } finally {
49368
49782
  active.delete(number);
49369
49783
  }
@@ -49449,14 +49863,33 @@ var PdfObjectReader = class {
49449
49863
  }
49450
49864
  };
49451
49865
  async function openPdfObjectReader(source, storage, options = {}) {
49452
- const xrefOptions = { maxNodes: 65536, maxTokenBytes: 1048576, maxRecursionDepth: 100, ...options, ...options.xref };
49866
+ let backingFailure;
49867
+ const callerBackingError = options.onBackingError;
49868
+ const xrefBackingError = options.xref?.onBackingError;
49869
+ const onBackingError = (error) => {
49870
+ backingFailure = { error };
49871
+ callerBackingError?.(error);
49872
+ };
49873
+ options = { ...options, onBackingError };
49874
+ const canRepair = (error) => !(backingFailure && Object.is(backingFailure.error, error)) && error instanceof PdfError && error.code === "E_PARSE";
49875
+ const xrefOptions = {
49876
+ maxNodes: 65536,
49877
+ maxTokenBytes: 1048576,
49878
+ maxRecursionDepth: 100,
49879
+ ...options,
49880
+ ...options.xref,
49881
+ onBackingError(error) {
49882
+ onBackingError(error);
49883
+ if (xrefBackingError !== callerBackingError) xrefBackingError?.(error);
49884
+ }
49885
+ };
49453
49886
  let crossReference;
49454
49887
  let repaired = false;
49455
49888
  try {
49456
49889
  crossReference = await openPdfCrossReference(source, storage, xrefOptions);
49457
49890
  } catch (error) {
49458
49891
  options.signal?.throwIfAborted();
49459
- if (options.recovery !== "repair" || !(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
49892
+ if (options.recovery !== "repair" || !canRepair(error)) throw error;
49460
49893
  crossReference = await recoverPdfReferences(source, storage, xrefOptions);
49461
49894
  repaired = true;
49462
49895
  }
@@ -49471,7 +49904,7 @@ async function openPdfObjectReader(source, storage, options = {}) {
49471
49904
  const pages = root?.value.kind === "dict" && !root.stream ? dictGet(root.value, "Pages") : void 0;
49472
49905
  valid = pages?.kind === "ref" || pages?.kind === "dict";
49473
49906
  } catch (error) {
49474
- if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
49907
+ if (!canRepair(error)) throw error;
49475
49908
  }
49476
49909
  if (!valid) {
49477
49910
  await reader.close();
@@ -49534,7 +49967,7 @@ async function openPdfObjectReader(source, storage, options = {}) {
49534
49967
  try {
49535
49968
  yield* currentReader.objectStreamEntries(object.objectNumber, object.generationNumber);
49536
49969
  } catch (error) {
49537
- if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
49970
+ if (!canRepair(error)) throw error;
49538
49971
  }
49539
49972
  }
49540
49973
  }
@@ -49557,7 +49990,7 @@ async function openPdfObjectReader(source, storage, options = {}) {
49557
49990
  try {
49558
49991
  object = await reader.get(entry.objectNumber, entry.generationNumber ?? 0);
49559
49992
  } catch (error) {
49560
- if (error instanceof PdfError && error.code === "E_PARSE") continue;
49993
+ if (canRepair(error)) continue;
49561
49994
  throw error;
49562
49995
  }
49563
49996
  if (object?.value.kind !== "dict") continue;
@@ -49711,7 +50144,7 @@ async function* parseContentRangeOperators(source, storage, options = {}) {
49711
50144
  }
49712
50145
  if (!Number.isSafeInteger(limits.chunkBytes) || limits.chunkBytes < 8) throw new RangeError("chunkBytes must be at least 8");
49713
50146
  const { signal } = options;
49714
- const lexer = new CosRangeLexer(source, { maxTokenBytes: limits.maxTokenBytes, knownCommands: PDF_KNOWN_COMMANDS, ...options.pathStorage ? { stringStorage: options.pathStorage } : {}, ...signal ? { signal } : {} });
50147
+ const lexer = new CosRangeLexer(source, { compactNumbers: options.compactNumbers ?? false, compactKeywords: options.compactKeywords ?? false, maxTokenBytes: limits.maxTokenBytes, knownCommands: PDF_KNOWN_COMMANDS, ...options.pathStorage ? { stringStorage: options.pathStorage } : {}, ...signal ? { signal } : {} });
49715
50148
  const stack = new PdfOperandStack(storage, limits);
49716
50149
  const backedStack = options.pathStorage ? new StoredMetadataStack(options.pathStorage, signal) : void 0;
49717
50150
  const operands = backedStack ?? stack;
@@ -54597,7 +55030,7 @@ async function resolveRetainedFont(document2, storage, resources, name, options
54597
55030
  }
54598
55031
  let value;
54599
55032
  if (step.value.kind === "resolve") {
54600
- const retained = await document2.lookup(step.value.node, options.resourceStorage ? { arrayStorage: options.resourceStorage, storedArrayKeys: ["Widths", "W", "Differences"], storeRootArray: step.value.storeRootArray ?? false } : {});
55033
+ const retained = await document2.lookup(step.value.node, options.resourceStorage ? { dictionaryStorage: options.resourceStorage, storedDictionaryKeys: ["Font", "XObject", "Properties"], storeRootDictionary: step.value.storeRootDictionary ?? false, arrayStorage: options.resourceStorage, storedArrayKeys: ["Widths", "W", "Differences"], storeRootArray: step.value.storeRootArray ?? false } : {});
54601
55034
  value = retained?.value;
54602
55035
  if (retained?.stream) {
54603
55036
  if (retained.value.kind !== "dict" || !retained.reference) throw new PdfError("E_PARSE", "Font stream has no retained identity");
@@ -54606,6 +55039,9 @@ async function resolveRetainedFont(document2, storage, resources, name, options
54606
55039
  identities.set(stream, retained.reference);
54607
55040
  value = stream;
54608
55041
  }
55042
+ } else if (step.value.kind === "dictionary-entry") {
55043
+ const record = await readStoredRecord(step.value.entries.storage, step.value.position, signal);
55044
+ value = cosArray([record.value.key, record.value.value, cosNumber(record.next)]);
54609
55045
  } else if (step.value.kind === "font-encoding") {
54610
55046
  const array = step.value.array;
54611
55047
  value = await StoredFontEncoding.create(() => array.storedItems ? readStoredItems(array.storedItems, signal) : array.items, options.resourceStorage, { onAllocation: (bytes) => allocation.admit(bytes), ...signal ? { signal } : {} });
@@ -54934,6 +55370,9 @@ async function* evaluateRetainedContentSteps(document2, content, params, storage
54934
55370
  reply = { kind: "dash-array", value: await storeDashArray(request.array, request.storage, request.resolveReferences ? resolve2 : async (node) => node, signal) };
54935
55371
  break;
54936
55372
  }
55373
+ case "dictionary-value":
55374
+ reply = { kind: "resolved", node: await readPdfDictionaryValue(request.dict, request.key, signal) };
55375
+ break;
54937
55376
  case "array-reference":
54938
55377
  reply = { kind: "resolved", node: cosBool(await memberships.has(request.items, request.objectNumber)) };
54939
55378
  break;
@@ -57151,122 +57590,6 @@ function resolveDestinationPageIndex(doc, destOrActionNode) {
57151
57590
  return void 0;
57152
57591
  }
57153
57592
 
57154
- // packages/pdf-ast/src/cos/name-index.ts
57155
- var PdfNameIndex = class {
57156
- constructor(storage, maximum10 = Infinity, signal) {
57157
- this.storage = storage;
57158
- this.maximum = maximum10;
57159
- this.signal = signal;
57160
- const limit10 = typeof maximum10 === "function" ? maximum10() : maximum10;
57161
- if (limit10 !== Infinity && (!Number.isSafeInteger(limit10) || limit10 < 0)) throw new RangeError("Invalid name staging limit");
57162
- }
57163
- storage;
57164
- maximum;
57165
- signal;
57166
- tail = /* @__PURE__ */ new Map();
57167
- hot = /* @__PURE__ */ new Map();
57168
- levels = [];
57169
- nextNode = 2;
57170
- nextName = 0;
57171
- closed = false;
57172
- get stagedBytes() {
57173
- return this.levels.reduce((sum, index2) => sum + (index2?.size ?? 0) * 32, 0);
57174
- }
57175
- async get(edge) {
57176
- if (this.tail.has(edge)) return this.tail.get(edge);
57177
- if (this.hot.has(edge)) return this.hot.get(edge);
57178
- for (const level of this.levels) {
57179
- const entry = await level?.get(edge, this.signal);
57180
- if (entry) {
57181
- if (this.hot.size < 256) this.hot.set(edge, entry.offset);
57182
- return entry.offset;
57183
- }
57184
- }
57185
- return void 0;
57186
- }
57187
- async insert(edge, node) {
57188
- this.tail.set(edge, node);
57189
- if (this.hot.size < 256) this.hot.set(edge, node);
57190
- if (this.tail.size < 64) return;
57191
- let level = 0;
57192
- while (this.levels[level]) level++;
57193
- const inputs = this.levels.slice(0, level);
57194
- const tail = this.tail;
57195
- const signal = this.signal;
57196
- async function* rows() {
57197
- for (const [objectNumber, offset] of tail) yield { objectNumber, offset, type: "uncompressed" };
57198
- for (const index2 of inputs) yield* index2.entries(signal);
57199
- }
57200
- const limit10 = typeof this.maximum === "function" ? this.maximum() : this.maximum;
57201
- const remaining = Math.min(limit10, Number.MAX_SAFE_INTEGER) - this.stagedBytes;
57202
- if (remaining < 0) throw new PdfError("E_LIMIT", "PDF name staging byte limit exceeded");
57203
- const combined = await PdfObjectIndex.build(rows(), this.storage, {
57204
- runEntries: 64,
57205
- chunkBytes: 2048,
57206
- cacheBytes: 2048,
57207
- maxStagingBytes: remaining,
57208
- ...signal ? { signal } : {}
57209
- });
57210
- try {
57211
- for (let i = 0; i < level; i++) {
57212
- await this.levels[i].close();
57213
- this.levels[i] = void 0;
57214
- }
57215
- this.levels[level] = combined;
57216
- this.tail.clear();
57217
- } catch (error) {
57218
- try {
57219
- await combined.close();
57220
- } catch {
57221
- }
57222
- throw error;
57223
- }
57224
- }
57225
- async intern(value) {
57226
- if (this.closed) throw new PdfError("E_CAPABILITY", "PDF name index is closed");
57227
- this.signal?.throwIfAborted();
57228
- let node = 1, newPath = false;
57229
- const units = typeof value === "string" ? (function* () {
57230
- for (let i = 0; i < value.length; i++) yield value.charCodeAt(i);
57231
- })() : value;
57232
- let work = 0;
57233
- for await (const code of units) {
57234
- this.signal?.throwIfAborted();
57235
- if (!Number.isInteger(code) || code < 0 || code > 65535) throw new RangeError("Invalid PDF name code unit");
57236
- if (++work % 512 === 0) {
57237
- await new Promise((resolve2) => setTimeout(resolve2, 0));
57238
- this.signal?.throwIfAborted();
57239
- }
57240
- for (const unit of [code & 255, code >>> 8]) {
57241
- const edge = node * 257 + unit + 1;
57242
- let child = newPath ? void 0 : await this.get(edge);
57243
- if (child === void 0) {
57244
- if (this.nextNode > Math.floor(Number.MAX_SAFE_INTEGER / 257) - 1) throw new PdfError("E_LIMIT", "PDF name index address limit exceeded");
57245
- child = this.nextNode++;
57246
- await this.insert(edge, child);
57247
- newPath = true;
57248
- }
57249
- node = child;
57250
- }
57251
- }
57252
- const terminal = node * 257;
57253
- const existing = newPath ? void 0 : await this.get(terminal);
57254
- if (existing !== void 0) return { index: existing, added: false };
57255
- const index2 = this.nextName++;
57256
- await this.insert(terminal, index2);
57257
- return { index: index2, added: true };
57258
- }
57259
- async close() {
57260
- if (this.closed) return;
57261
- this.closed = true;
57262
- const results = await Promise.allSettled(this.levels.map((index2) => index2?.close()));
57263
- this.tail.clear();
57264
- this.hot.clear();
57265
- this.levels.length = 0;
57266
- for (const result of results) if (result.status === "rejected") throw result.reason;
57267
- }
57268
- };
57269
-
57270
57593
  // packages/pdf-ast/src/extract/retained-form-fields.ts
57271
57594
  import { IntegerTable as IntegerTable4, PagedStorage as PagedStorage6 } from "@poe-platform/safe-fs/storage";
57272
57595
 
@@ -58118,7 +58441,7 @@ var PdfMergeOutlines = class {
58118
58441
  if (node.kind === "ref" && !await seen.add(node.objectNumber)) continue;
58119
58442
  const dict = (await document2.lookup(node))?.value;
58120
58443
  if (dict?.kind !== "dict") continue;
58121
- yield dict;
58444
+ yield { dict, level: depth + 1 };
58122
58445
  if (outlines) {
58123
58446
  await push(dictGet(dict, "Next"), depth);
58124
58447
  await push(dictGet(dict, "First"), depth + 1);
@@ -58140,7 +58463,7 @@ var PdfMergeOutlines = class {
58140
58463
  }
58141
58464
  }
58142
58465
  }
58143
- async append(document2, pageOffset, includeUntitled = false) {
58466
+ async append(document2, pageOffset, includeUntitled = false, includeNameTitles = false) {
58144
58467
  const resolve2 = async (node) => (await document2.lookup(node))?.value;
58145
58468
  const catalog = await resolve2(document2.crossReference.rootRef);
58146
58469
  if (catalog?.kind !== "dict") return;
@@ -58151,7 +58474,7 @@ var PdfMergeOutlines = class {
58151
58474
  const legacy = await resolve2(dictGet(catalog, "Dests")), direct = legacy?.kind === "dict" ? dictGet(legacy, name) : void 0;
58152
58475
  if (direct) return direct;
58153
58476
  const names = await resolve2(dictGet(catalog, "Names"));
58154
- if (names?.kind === "dict") for await (const tree of this.walk(document2, dictGet(names, "Dests"), false)) {
58477
+ if (names?.kind === "dict") for await (const { dict: tree } of this.walk(document2, dictGet(names, "Dests"), false)) {
58155
58478
  const pairs = await resolve2(dictGet(tree, "Names"));
58156
58479
  if (pairs?.kind === "array") for (let i = 0; i + 1 < pairs.items.length; i += 2) {
58157
58480
  await this.checkpoint();
@@ -58184,10 +58507,10 @@ var PdfMergeOutlines = class {
58184
58507
  return number?.kind === "number" && number.value >= 0 && number.value < pageCount ? Math.round(number.value) : 0;
58185
58508
  };
58186
58509
  try {
58187
- for await (const outline of this.walk(document2, dictGet(outlines, "First"), true)) {
58188
- const title = await resolve2(dictGet(outline, "Title")), text = title?.kind === "string" ? decodePdfString(title) : "";
58510
+ for await (const { dict: outline, level } of this.walk(document2, dictGet(outlines, "First"), true)) {
58511
+ const title = await resolve2(dictGet(outline, "Title")), text = title?.kind === "string" ? decodePdfString(title) : includeNameTitles && title?.kind === "name" ? title.decoded : "";
58189
58512
  const index2 = await destination(dictGet(outline, "Dest") ?? dictGet(outline, "A"));
58190
- if (text || includeUntitled) await this.objects.set({ objectNumber: ++this.count, generationNumber: 0, value: cosDict({ Title: cosString(text), Page: cosNumber(pageOffset + index2) }) });
58513
+ if (text || includeUntitled) await this.objects.set({ objectNumber: ++this.count, generationNumber: 0, value: cosDict({ Title: cosString(text), Page: cosNumber(pageOffset + index2), Level: cosNumber(level) }) });
58191
58514
  }
58192
58515
  } catch (error) {
58193
58516
  failed = true;
@@ -58199,11 +58522,14 @@ var PdfMergeOutlines = class {
58199
58522
  }
58200
58523
  }
58201
58524
  async *entries() {
58525
+ for await (const { title, pageIndex } of this.details()) yield { title, pageIndex };
58526
+ }
58527
+ async *details() {
58202
58528
  for await (const object of this.objects.objects()) {
58203
58529
  await this.checkpoint();
58204
- const row = object.value, title = dictGet(row, "Title"), index2 = dictGet(row, "Page");
58530
+ const row = object.value, title = dictGet(row, "Title"), index2 = dictGet(row, "Page"), level = dictGet(row, "Level");
58205
58531
  if (title?.kind !== "string" || index2?.kind !== "number") throw new PdfError("E_PARSE", "Invalid staged outline summary");
58206
- yield { title: decodePdfString(title), pageIndex: index2.value };
58532
+ yield { title: decodePdfString(title), pageIndex: index2.value, level: level?.kind === "number" ? level.value : 1 };
58207
58533
  }
58208
58534
  }
58209
58535
  async finish(target, catalog, pageCount, page2) {
@@ -59009,6 +59335,7 @@ async function prepareRetainedPageContent(document2, page2, pageResources, stora
59009
59335
  const request = step.value;
59010
59336
  let result;
59011
59337
  if (request.kind === "resolve" || request.kind === "catalog") result = await resolve2(request.kind === "catalog" ? document2.crossReference.rootRef : request.node, request.kind === "resolve" ? request.arrayPathPrefix : void 0);
59338
+ else if (request.kind === "dictionary-merge") result = await mergePdfResourceDictionaries(request.destination, request.source, storage, options.signal);
59012
59339
  else if (request.kind === "array-reference") result = cosBool(await memberships.has(request.items, request.objectNumber));
59013
59340
  else if (request.kind === "array-item") {
59014
59341
  const record = await readStoredRecord(request.items.storage, request.position, options.signal);
@@ -59298,7 +59625,7 @@ async function markedText(document2, page2, mcid, storage, options) {
59298
59625
  var boundary = boundary2, scan = scan2;
59299
59626
  source = await PdfFileSource.fromStream(storage.fs, storage.directory, input(), { chunkBytes, cacheBytes: chunkBytes, maxInputBytes: maximum10, ...signal ? { signal } : {} });
59300
59627
  const resources = (await document2.lookup(dictGet(page2, "Resources")))?.value;
59301
- const properties = resources?.kind === "dict" ? (await document2.lookup(dictGet(resources, "Properties")))?.value : void 0;
59628
+ const properties = resources?.kind === "dict" ? (await document2.lookup(dictGet(resources, "Properties"), void 0, ["Properties"]))?.value : void 0;
59302
59629
  const operators2 = parseContentRangeOperators(source, storage, { chunkBytes, maxStagingBytes: maximum10 - source.size, ...signal ? { signal } : {} });
59303
59630
  let pending, matching = false, inText = false, part = 0, recorded = false;
59304
59631
  async function* fragments(command) {
@@ -59327,7 +59654,7 @@ async function markedText(document2, page2, mcid, storage, options) {
59327
59654
  await marks.push({ kind: "boolean", value: matching });
59328
59655
  if (operator !== "q") {
59329
59656
  const property = operands[1];
59330
- const dict = property?.kind === "name" && properties?.kind === "dict" ? (await document2.lookup(dictGet(properties, property.decoded)))?.value : property;
59657
+ const dict = property?.kind === "name" && properties?.kind === "dict" ? (await document2.lookup(await readPdfDictionaryValue(properties, property.decoded, signal)))?.value : property;
59331
59658
  const number = dict?.kind === "dict" ? (await document2.lookup(dictGet(dict, "MCID")))?.value : void 0;
59332
59659
  if (number?.kind === "number") matching = number.value === mcid;
59333
59660
  }
@@ -59726,8 +60053,8 @@ async function* walkRetainedImages(document2, storage, options) {
59726
60053
  const decodeOptions = { chunkBytes, ...options.maxDecodedBytes === void 0 ? {} : { maxDecodedBytes: options.maxDecodedBytes }, ...options.signal ? { signal: options.signal } : {} };
59727
60054
  let imageIndex = 0;
59728
60055
  let stagedBytes = 0;
59729
- async function dictionary(node) {
59730
- const value = await document2.lookup(node);
60056
+ async function dictionary(node, resourceKey) {
60057
+ const value = await document2.lookup(node, void 0, resourceKey ? [resourceKey] : void 0);
59731
60058
  return value?.value.kind === "dict" && !value.stream ? value.value : void 0;
59732
60059
  }
59733
60060
  async function number(node, fallback) {
@@ -59826,8 +60153,8 @@ async function* walkRetainedImages(document2, storage, options) {
59826
60153
  } else if (op.operator === "Do") {
59827
60154
  const name = op.operands[0];
59828
60155
  if (name?.kind !== "name") continue;
59829
- const objects = await dictionary(dictGet(activeResources, "XObject"));
59830
- const target = await document2.lookup(objects ? dictGet(objects, name.decoded) : void 0);
60156
+ const objects = await dictionary(dictGet(activeResources, "XObject"), "XObject");
60157
+ const target = await document2.lookup(objects ? await readPdfDictionaryValue(objects, name.decoded, options.signal) : void 0);
59831
60158
  if (target?.value.kind !== "dict" || !target.stream || !target.reference) continue;
59832
60159
  const subtype = (await document2.lookup(dictGet(target.value, "Subtype")))?.value;
59833
60160
  if (subtype?.kind !== "name") continue;
@@ -59888,8 +60215,8 @@ async function* walkRetainedImages(document2, storage, options) {
59888
60215
  yield* content(page2.streamContents(), resources, identity, /* @__PURE__ */ new Set(), 0);
59889
60216
  const patterns = await dictionary(dictGet(resources, "Pattern"));
59890
60217
  if (patterns) for (const entry of patterns.entries) yield* auxiliary(entry.value, resources);
59891
- const fonts = await dictionary(dictGet(resources, "Font"));
59892
- if (fonts) for (const entry of fonts.entries) {
60218
+ const fonts = await dictionary(dictGet(resources, "Font"), "Font");
60219
+ if (fonts) for await (const entry of readPdfDictionaryEntries(fonts, options.signal)) {
59893
60220
  const font = await dictionary(entry.value);
59894
60221
  if (!font) continue;
59895
60222
  const subtype = (await document2.lookup(dictGet(font, "Subtype")))?.value;
@@ -59904,8 +60231,8 @@ async function* walkRetainedImages(document2, storage, options) {
59904
60231
  const appearance = annotation ? await dictionary(dictGet(annotation, "AP")) : void 0;
59905
60232
  if (appearance) yield* auxiliary(dictGet(appearance, "N"), resources);
59906
60233
  }
59907
- const objects = await dictionary(dictGet(resources, "XObject"));
59908
- if (objects) for (const entry of objects.entries) {
60234
+ const objects = await dictionary(dictGet(resources, "XObject"), "XObject");
60235
+ if (objects) for await (const entry of readPdfDictionaryEntries(objects, options.signal)) {
59909
60236
  const ref = entry.value;
59910
60237
  if (ref.kind === "ref" && !(await seen.intern(`${ref.objectNumber}:${ref.generationNumber}`)).added) continue;
59911
60238
  const target = await document2.lookup(ref);
@@ -59942,8 +60269,8 @@ async function* walkRetainedFonts(document2, storage, options) {
59942
60269
  const last = options.lastPage ?? Infinity;
59943
60270
  if (!Number.isSafeInteger(first) || first < 1 || last !== Infinity && (!Number.isSafeInteger(last) || last < first)) throw new RangeError("Invalid PDF font page range");
59944
60271
  let failed = false;
59945
- async function dictionary(node) {
59946
- const resolved = await document2.lookup(node);
60272
+ async function dictionary(node, resourceKey) {
60273
+ const resolved = await document2.lookup(node, void 0, resourceKey ? [resourceKey] : void 0);
59947
60274
  return resolved?.value.kind === "dict" && !resolved.stream ? resolved.value : void 0;
59948
60275
  }
59949
60276
  async function* font(node, key, depth) {
@@ -59979,8 +60306,8 @@ async function* walkRetainedFonts(document2, storage, options) {
59979
60306
  options.signal?.throwIfAborted();
59980
60307
  if (!value) return;
59981
60308
  if (depth > options.maxDepth) throw new PdfError("E_LIMIT", "PDF font resource depth limit exceeded");
59982
- const fonts = await dictionary(dictGet(value, "Font"));
59983
- if (fonts) for (const entry of fonts.entries) yield* font(entry.value, entry.key.decoded, depth);
60309
+ const fonts = await dictionary(dictGet(value, "Font"), "Font");
60310
+ if (fonts) for await (const entry of readPdfDictionaryEntries(fonts, options.signal)) yield* font(entry.value, entry.key.decoded, depth);
59984
60311
  const states = await dictionary(dictGet(value, "ExtGState"));
59985
60312
  if (states) for (const entry of states.entries) {
59986
60313
  const state = await dictionary(entry.value);
@@ -59988,9 +60315,9 @@ async function* walkRetainedFonts(document2, storage, options) {
59988
60315
  if (gsFont?.kind === "array" && gsFont.items[0]) yield* font(gsFont.items[0], `ExtGS_${entry.key.decoded}`, depth);
59989
60316
  }
59990
60317
  for (const key of ["XObject", "Pattern"]) {
59991
- const objects = await dictionary(dictGet(value, key));
60318
+ const objects = await dictionary(dictGet(value, key), key);
59992
60319
  if (!objects) continue;
59993
- for (const entry of objects.entries) {
60320
+ for await (const entry of readPdfDictionaryEntries(objects, options.signal)) {
59994
60321
  if (entry.value.kind === "ref" && !(await names.intern(`form:${entry.value.objectNumber}`)).added) continue;
59995
60322
  const resolved = await document2.lookup(entry.value);
59996
60323
  if (!resolved?.stream || resolved.value.kind !== "dict") continue;
@@ -60165,6 +60492,7 @@ var PdfRetainedDocument = class _PdfRetainedDocument {
60165
60492
  if (arrayPathPrefix) arrays = {
60166
60493
  ...arrays,
60167
60494
  arrayPathPrefix,
60495
+ ...arrayPathPrefix.length && arrays.storedDictionaryKeys?.includes(arrayPathPrefix[arrayPathPrefix.length - 1]) ? { storeRootDictionary: true } : {},
60168
60496
  ...arrayPathPrefix.length && arrays.storedArrayKeys?.includes(arrayPathPrefix[arrayPathPrefix.length - 1]) ? { storeRootArray: true } : {},
60169
60497
  ...arrayPathPrefix.length && arrays.storedStringKeys?.includes(arrayPathPrefix[arrayPathPrefix.length - 1]) ? { storeRootString: true } : {}
60170
60498
  };
@@ -60573,6 +60901,29 @@ var PdfRetainedDocument = class _PdfRetainedDocument {
60573
60901
  const work = visit(this);
60574
60902
  return work;
60575
60903
  }
60904
+ outlineDetails() {
60905
+ async function* visit(doc) {
60906
+ doc.assertOpen();
60907
+ doc.walks.add(work);
60908
+ const storage = new PdfStagingStorage(doc.storage, doc.options.maxTraversalStagingBytes);
60909
+ const outlines = new PdfMergeOutlines(storage, doc.options.signal, Infinity);
60910
+ let failed = false;
60911
+ try {
60912
+ await outlines.append(doc, 0, false, true);
60913
+ yield* outlines.details();
60914
+ } catch (error) {
60915
+ failed = true;
60916
+ throw error;
60917
+ } finally {
60918
+ doc.walks.delete(work);
60919
+ await outlines.close().catch((error) => {
60920
+ if (!failed) throw error;
60921
+ });
60922
+ }
60923
+ }
60924
+ const work = visit(this);
60925
+ return work;
60926
+ }
60576
60927
  pageLabels() {
60577
60928
  async function* visit(doc) {
60578
60929
  doc.assertOpen();
@@ -61688,6 +62039,26 @@ async function* retainedCosObjects(document2, storage, options = {}) {
61688
62039
  yield identity;
61689
62040
  continue;
61690
62041
  }
62042
+ if (options.streamMode && options.streamMode !== "preserve" && object.value.kind === "dict") {
62043
+ const activeSignal = signal ?? new AbortController().signal;
62044
+ const input = document2.objects.decodeStream(entry.objectNumber, generationNumber);
62045
+ const staged2 = options.streamMode === "compress" ? await stageDeflatedPdf(input, storage, activeSignal, maxStreamBytes) : await PdfFileSource.fromStream(storage.fs, storage.directory, input, { signal: activeSignal, maxInputBytes: maxStreamBytes });
62046
+ let failed2 = false;
62047
+ try {
62048
+ const value = { ...object.value, entries: object.value.entries.filter((item) => item.key.decoded !== "Filter" && item.key.decoded !== "DecodeParms") };
62049
+ if (options.streamMode === "compress") dictSet(value, "Filter", cosName("FlateDecode"));
62050
+ dictSet(value, "Length", cosNumber(staged2.size));
62051
+ yield { ...identity, value, stream: { decoded: true, length: staged2.size, chunks: staged2.stream(0, staged2.size, activeSignal) } };
62052
+ } catch (error) {
62053
+ failed2 = true;
62054
+ throw error;
62055
+ } finally {
62056
+ await staged2.close().catch((error) => {
62057
+ if (!failed2) throw error;
62058
+ });
62059
+ }
62060
+ continue;
62061
+ }
61691
62062
  if (options.normalizeContent && object.decoded && object.value.kind === "dict") {
61692
62063
  const decoded2 = await PdfFileSource.fromStream(storage.fs, storage.directory, document2.objects.decodeStream(entry.objectNumber, generationNumber), { ...signal ? { signal } : {}, maxInputBytes: maxStreamBytes });
61693
62064
  let failed2 = false;
@@ -61906,7 +62277,7 @@ async function* saveRetainedDocumentChunks(document2, storage, options = {}) {
61906
62277
  }
61907
62278
  }
61908
62279
  try {
61909
- for await (const object of retainedCosObjects(document2, storage, { ...options.normalizeContent ? { normalizeContent: true } : {}, ...options.maxObjects === void 0 ? {} : { maxObjects: options.maxObjects }, ...options.maxOutputBytes === void 0 ? {} : { maxStreamBytes: options.maxOutputBytes }, signal })) {
62280
+ for await (const object of retainedCosObjects(document2, storage, { ...options.streamMode ? { streamMode: options.streamMode } : {}, ...options.normalizeContent ? { normalizeContent: true } : {}, ...options.maxObjects === void 0 ? {} : { maxObjects: options.maxObjects }, ...options.maxOutputBytes === void 0 ? {} : { maxStreamBytes: options.maxOutputBytes }, signal })) {
61910
62281
  if (!object.stream && object.value.kind === "dict" && dictGet(object.value, "Linearized") !== void 0) mayLinearize = true;
61911
62282
  await objects.set(object);
61912
62283
  }
@@ -62018,8 +62389,331 @@ async function* saveRetainedDocumentChunks(document2, storage, options = {}) {
62018
62389
  }
62019
62390
  }
62020
62391
 
62392
+ // packages/pdf-ast/src/edit/retained-info-updates.ts
62393
+ import { PagedStorage as PagedStorage14 } from "@poe-platform/safe-fs/storage";
62394
+
62395
+ // packages/pdf-ast/src/edit/retained-bookmarks.ts
62396
+ import { PagedStorage as PagedStorage13 } from "@poe-platform/safe-fs/storage";
62397
+ async function setRetainedBookmarks(store, storage, root, pageCount, pageReference, bookmarks, signal, maxDepth = Infinity) {
62398
+ if (!pageCount) return;
62399
+ const catalog = await store.get(root.objectNumber);
62400
+ if (catalog?.value.kind !== "dict") return;
62401
+ const frames = new PagedStorage13({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62402
+ const base = frames.allocate(0);
62403
+ let depth = 0, capacity = 0, failed = false, work = 0;
62404
+ async function write(index2, frame) {
62405
+ if (index2 >= capacity) {
62406
+ frames.allocate(24);
62407
+ capacity++;
62408
+ }
62409
+ const bytes = new Uint8Array(24), view = new DataView(bytes.buffer);
62410
+ view.setFloat64(0, frame.number);
62411
+ view.setFloat64(8, frame.last);
62412
+ view.setFloat64(16, frame.count);
62413
+ await frames.write(base + index2 * 24, bytes);
62414
+ }
62415
+ async function read(index2) {
62416
+ const bytes = await frames.read(base + index2 * 24, 24), view = new DataView(bytes.buffer, bytes.byteOffset, bytes.length);
62417
+ return { number: view.getFloat64(0), last: view.getFloat64(8), count: view.getFloat64(16) };
62418
+ }
62419
+ try {
62420
+ for await (const bookmark of bookmarks) {
62421
+ signal.throwIfAborted();
62422
+ if (++work % 64 === 0) {
62423
+ await new Promise((resolve2) => setTimeout(resolve2, 0));
62424
+ signal.throwIfAborted();
62425
+ }
62426
+ if (!Number.isSafeInteger(bookmark.level) || !Number.isSafeInteger(bookmark.pageNumber)) throw new RangeError("Bookmark level and page number must be safe integers");
62427
+ if (!depth) {
62428
+ const outlines = await store.allocate(cosDict({ Type: cosName("Outlines") }));
62429
+ dictSet(catalog.value, "Outlines", outlines);
62430
+ await store.set(catalog);
62431
+ await write(0, { number: outlines.objectNumber, last: 0, count: 0 });
62432
+ depth = 1;
62433
+ }
62434
+ const target = Math.max(1, bookmark.level);
62435
+ depth = Math.min(depth, target);
62436
+ while (depth < target) {
62437
+ const parent2 = await read(depth - 1);
62438
+ if (!parent2.last) break;
62439
+ if (depth >= maxDepth) throw new PdfError("E_LIMIT", "PDF bookmark depth limit exceeded");
62440
+ await write(depth, { number: parent2.last, last: 0, count: 0 });
62441
+ depth++;
62442
+ }
62443
+ const frame = await read(depth - 1), parent = await store.get(frame.number);
62444
+ if (parent.value.kind !== "dict") throw new PdfError("E_PARSE", "Expected outline parent dictionary");
62445
+ const page2 = await pageReference(Math.max(0, Math.min(pageCount - 1, bookmark.pageNumber - 1)));
62446
+ const value = cosDict({ Title: cosString(bookmark.title), Parent: cosRef(frame.number), Dest: cosArray([page2, cosName("XYZ"), { kind: "null" }, { kind: "null" }, { kind: "null" }]) });
62447
+ const item = await store.allocate(value);
62448
+ if (frame.last) {
62449
+ const previous = await store.get(frame.last);
62450
+ if (previous.value.kind !== "dict") throw new PdfError("E_PARSE", "Expected outline sibling dictionary");
62451
+ dictSet(previous.value, "Next", item);
62452
+ await store.set(previous);
62453
+ dictSet(value, "Prev", cosRef(frame.last));
62454
+ await store.set({ objectNumber: item.objectNumber, generationNumber: item.generationNumber, value });
62455
+ } else dictSet(parent.value, "First", item);
62456
+ dictSet(parent.value, "Last", item);
62457
+ dictSet(parent.value, "Count", cosNumber(++frame.count));
62458
+ await store.set(parent);
62459
+ frame.last = item.objectNumber;
62460
+ await write(depth - 1, frame);
62461
+ }
62462
+ } catch (error) {
62463
+ failed = true;
62464
+ throw error;
62465
+ } finally {
62466
+ await frames.close().catch((error) => {
62467
+ if (!failed) throw error;
62468
+ });
62469
+ }
62470
+ }
62471
+
62472
+ // packages/pdf-ast/src/edit/retained-info-updates.ts
62473
+ async function applyRetainedInfoUpdates(document2, store, storage, count, getPage, updates, signal, maxDepth) {
62474
+ const pages = new PagedStorage14({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62475
+ const base = pages.allocate(count * 4 * 48), heads = [-1, -1, -1, -1], tails = [-1, -1, -1, -1];
62476
+ const labels = new PdfMutableObjectStore(storage, { signal }), bookmarks = new PdfMutableObjectStore(storage, { signal });
62477
+ let infoRef = document2.crossReference.infoRef, idArray = document2.crossReference.idArray, labelCount = 0, work = 0, failed = false;
62478
+ const rootRef = document2.crossReference.rootRef;
62479
+ async function checkpoint() {
62480
+ signal.throwIfAborted();
62481
+ if (++work % 64 === 0) await new Promise((resolve2) => setTimeout(resolve2, 0));
62482
+ signal.throwIfAborted();
62483
+ }
62484
+ const position = (group, index2) => base + (group * count + index2) * 48;
62485
+ try {
62486
+ for await (const update of updates) {
62487
+ await checkpoint();
62488
+ if (update.kind === "info") {
62489
+ const standard = ["Title", "Author", "Subject", "Keywords", "Creator", "Producer"].includes(update.key);
62490
+ let info3 = infoRef ? await store.get(infoRef.objectNumber) : void 0;
62491
+ if (infoRef && info3?.value.kind !== "dict") {
62492
+ const resolved = await document2.lookup(infoRef);
62493
+ if (resolved?.value.kind === "dict" && resolved.reference) info3 = await store.get(resolved.reference.objectNumber);
62494
+ }
62495
+ if (!infoRef || standard && info3?.value.kind !== "dict") {
62496
+ infoRef = await store.allocate(cosDict(!standard ? { Title: cosString("") } : {}));
62497
+ info3 = await store.get(infoRef.objectNumber);
62498
+ }
62499
+ if (info3?.value.kind === "dict") {
62500
+ dictSet(info3.value, update.key, cosString(update.value));
62501
+ await store.set(info3);
62502
+ }
62503
+ } else if (update.kind === "id") {
62504
+ if (idArray === document2.crossReference.idArray) {
62505
+ const first = await document2.lookup(idArray?.items[0]), second = await document2.lookup(idArray?.items[1]);
62506
+ const a = first?.value.kind === "string" ? first.value.bytes : new Uint8Array(16), b = second?.value.kind === "string" ? second.value.bytes : a;
62507
+ idArray = cosArray([cosHexString(a), cosHexString(b)]);
62508
+ }
62509
+ idArray.items[update.index] = cosHexString(new Uint8Array(update.bytes));
62510
+ } else if (update.kind === "page") {
62511
+ const index2 = update.pageNumber - 1;
62512
+ if (!Number.isSafeInteger(index2) || index2 < 0 || index2 >= count) continue;
62513
+ const group = ["rotation", "dimensions", "media", "crop"].indexOf(update.property), size = group === 0 ? 1 : group === 1 ? 2 : 4;
62514
+ if (update.values.length !== size || !update.values.every(Number.isFinite)) throw new RangeError("Invalid page property values");
62515
+ const offset = position(group, index2), bytes = await pages.read(offset, 48), view = new DataView(bytes.buffer, bytes.byteOffset, bytes.length);
62516
+ if (!view.getFloat64(0)) {
62517
+ view.setFloat64(0, 1);
62518
+ view.setFloat64(8, -1);
62519
+ if (tails[group] >= 0) {
62520
+ const link2 = new Uint8Array(8);
62521
+ new DataView(link2.buffer).setFloat64(0, index2);
62522
+ await pages.write(position(group, tails[group]) + 8, link2);
62523
+ } else heads[group] = index2;
62524
+ tails[group] = index2;
62525
+ }
62526
+ for (let i = 0; i < size; i++) view.setFloat64(16 + i * 8, update.values[i]);
62527
+ await pages.write(offset, bytes);
62528
+ } else if (update.kind === "label") {
62529
+ const value = cosDict({ St: cosNumber(update.start) });
62530
+ if (update.prefix) dictSet(value, "P", cosString(update.prefix));
62531
+ if (update.style) dictSet(value, "S", cosName(update.style));
62532
+ await labels.allocate(cosArray([cosNumber(update.index), value]));
62533
+ labelCount++;
62534
+ } else await bookmarks.allocate(cosArray([cosString(update.title), cosNumber(update.level), cosNumber(update.pageNumber)]));
62535
+ }
62536
+ for (let group = 0; group < 4; group++) for (let index2 = heads[group]; index2 >= 0; ) {
62537
+ await checkpoint();
62538
+ const bytes = await pages.read(position(group, index2), 48), view = new DataView(bytes.buffer, bytes.byteOffset, bytes.length), page2 = await getPage(index2);
62539
+ if (group === 0) dictSet(page2.dict, "Rotate", cosNumber((Math.round(view.getFloat64(16) / 90) * 90 % 360 + 360) % 360));
62540
+ else {
62541
+ const values = group === 1 ? [0, 0, view.getFloat64(16), view.getFloat64(24)] : [16, 24, 32, 40].map((offset) => view.getFloat64(offset));
62542
+ dictSet(page2.dict, group === 3 ? "CropBox" : "MediaBox", cosArray(values.map((value) => cosNumber(value))));
62543
+ }
62544
+ await store.set({ objectNumber: page2.reference.objectNumber, generationNumber: page2.reference.generationNumber, value: page2.dict });
62545
+ index2 = view.getFloat64(8);
62546
+ }
62547
+ if (labelCount) {
62548
+ const root = await store.get(rootRef.objectNumber);
62549
+ if (root?.value.kind === "dict") {
62550
+ const ref = await store.allocate(cosDict({}));
62551
+ dictSet(root.value, "PageLabels", ref);
62552
+ await store.set(root);
62553
+ async function* chunks() {
62554
+ const encoder = new TextEncoder();
62555
+ yield encoder.encode("<<\n/Nums [ ");
62556
+ for await (const object of labels.objects()) {
62557
+ await checkpoint();
62558
+ if (object.value.kind !== "array") throw new Error("Invalid label record");
62559
+ for (const node of object.value.items) {
62560
+ yield* serializeCosNodeChunks(node, { signal });
62561
+ yield encoder.encode(" ");
62562
+ }
62563
+ }
62564
+ yield encoder.encode("]\n>>");
62565
+ }
62566
+ let length = 0;
62567
+ for await (const bytes of chunks()) length += bytes.length;
62568
+ await store.setSerializedValue({ objectNumber: ref.objectNumber, generationNumber: 0, body: { length, chunks: chunks() } });
62569
+ }
62570
+ }
62571
+ async function* outlineUpdates() {
62572
+ for await (const object of bookmarks.objects()) {
62573
+ await checkpoint();
62574
+ const value = object.value;
62575
+ if (value.kind !== "array" || value.items[0]?.kind !== "string" || value.items[1]?.kind !== "number" || value.items[2]?.kind !== "number") throw new Error("Invalid bookmark record");
62576
+ yield { title: decodePdfString(value.items[0]), level: value.items[1].value, pageNumber: value.items[2].value };
62577
+ }
62578
+ }
62579
+ await setRetainedBookmarks(store, storage, rootRef, count, async (index2) => (await getPage(index2)).reference, outlineUpdates(), signal, maxDepth);
62580
+ return { infoRef, idArray };
62581
+ } catch (error) {
62582
+ failed = true;
62583
+ throw error;
62584
+ } finally {
62585
+ const results = await Promise.allSettled([pages.close(), labels.close(), bookmarks.close()]);
62586
+ if (!failed) {
62587
+ for (const result of results) if (result.status === "rejected") await Promise.reject(result.reason);
62588
+ }
62589
+ }
62590
+ }
62591
+
62592
+ // packages/pdf-ast/src/edit/retained-append-attachments.ts
62593
+ async function appendRetainedAttachments(document2, target, storage, attachments, options = {}) {
62594
+ const signal = options.signal ?? new AbortController().signal, appended = new PdfMutableObjectStore(storage, { signal });
62595
+ let failed = false, count = 0;
62596
+ async function resolve2(node) {
62597
+ const found = await document2.lookup(node);
62598
+ return found?.stream ? void 0 : found;
62599
+ }
62600
+ async function save(reference, value) {
62601
+ await target.set({ objectNumber: reference.objectNumber, generationNumber: reference.generationNumber, value });
62602
+ }
62603
+ try {
62604
+ const root = await resolve2(document2.crossReference.rootRef);
62605
+ if (root?.value.kind !== "dict" || !root.reference) return;
62606
+ let owner = root;
62607
+ let names = await resolve2(dictGet(root.value, "Names"));
62608
+ if (names?.value.kind !== "dict") {
62609
+ const value = cosDict({}), reference = await target.allocate(value);
62610
+ names = { value, reference };
62611
+ dictSet(root.value, "Names", reference);
62612
+ await save(root.reference, root.value);
62613
+ }
62614
+ if (names.value.kind !== "dict") throw new Error("Invalid attachment names");
62615
+ if (names.reference) owner = names;
62616
+ let tree = await resolve2(dictGet(names.value, "EmbeddedFiles"));
62617
+ if (tree?.value.kind !== "dict") {
62618
+ const value = cosDict({ Names: cosArray([]) }), reference = await target.allocate(value);
62619
+ tree = { value, reference };
62620
+ dictSet(names.value, "EmbeddedFiles", reference);
62621
+ await save(owner.reference, owner.value);
62622
+ }
62623
+ if (tree.value.kind !== "dict") throw new Error("Invalid attachment tree");
62624
+ if (tree.reference) owner = tree;
62625
+ const existing = await resolve2(dictGet(tree.value, "Names")), namesMarker = cosArray([]);
62626
+ if (existing?.value.kind === "array" && existing.reference) owner = { value: namesMarker, reference: existing.reference };
62627
+ else dictSet(tree.value, "Names", namesMarker);
62628
+ let pageOwner, previousAnnots;
62629
+ const annotsMarker = cosArray([]);
62630
+ if (options.pageIndex !== void 0) for await (const page2 of document2.pages()) {
62631
+ if (page2.index !== options.pageIndex) continue;
62632
+ if (page2.reference) {
62633
+ const annots = await resolve2(dictGet(page2.dict, "Annots"));
62634
+ previousAnnots = annots?.value.kind === "array" ? annots.value : void 0;
62635
+ if (annots?.value.kind === "array" && annots.reference) pageOwner = { value: annotsMarker, reference: annots.reference };
62636
+ else {
62637
+ dictSet(page2.dict, "Annots", annotsMarker);
62638
+ pageOwner = { value: page2.dict, reference: page2.reference };
62639
+ }
62640
+ }
62641
+ break;
62642
+ }
62643
+ for await (const attachment of attachments) {
62644
+ signal.throwIfAborted();
62645
+ const compressed = await stageDeflatedPdf(attachment.chunks, storage, signal);
62646
+ let itemFailed = false;
62647
+ try {
62648
+ const embedded = await target.allocate();
62649
+ await target.set({ objectNumber: embedded.objectNumber, generationNumber: 0, value: cosDict({ Type: cosName("EmbeddedFile"), Filter: cosName("FlateDecode"), Length: cosNumber(compressed.size) }), stream: { decoded: true, length: compressed.size, chunks: compressed.stream(0, compressed.size, signal) } });
62650
+ const reference = await target.allocate(cosDict({ Type: cosName("Filespec"), F: cosString(attachment.filename), UF: cosString(attachment.filename), EF: cosDict({ F: embedded }) }));
62651
+ let annotation;
62652
+ if (pageOwner) annotation = await target.allocate(cosDict({ Type: cosName("Annot"), Subtype: cosName("FileAttachment"), Name: cosName("PushPin"), Contents: cosString(attachment.filename), FS: reference, Rect: cosArray([20, 20, 40, 40].map((value) => cosNumber(value))) }));
62653
+ await appended.set({ objectNumber: ++count, generationNumber: 0, value: cosArray([cosString(attachment.filename), reference, ...annotation ? [annotation] : []]) });
62654
+ } catch (error) {
62655
+ itemFailed = true;
62656
+ throw error;
62657
+ } finally {
62658
+ await compressed.close().catch((error) => {
62659
+ if (!itemFailed) throw error;
62660
+ });
62661
+ }
62662
+ }
62663
+ const encoder = new TextEncoder();
62664
+ async function* serialized(node) {
62665
+ signal.throwIfAborted();
62666
+ if (node === namesMarker || node === annotsMarker) {
62667
+ yield encoder.encode("[ ");
62668
+ const old = node === namesMarker ? existing?.value : previousAnnots;
62669
+ if (old?.kind === "array") for (const item of old.items) {
62670
+ yield* serializeCosNodeChunks(item, { signal });
62671
+ yield encoder.encode(" ");
62672
+ }
62673
+ for await (const pair of appended.objects()) {
62674
+ if (pair.value.kind !== "array") throw new Error("Invalid attachment pair");
62675
+ const items = node === namesMarker ? pair.value.items.slice(0, 2) : pair.value.items.slice(2);
62676
+ for (const item of items) {
62677
+ yield* serializeCosNodeChunks(item, { signal });
62678
+ yield encoder.encode(" ");
62679
+ }
62680
+ }
62681
+ yield encoder.encode("]");
62682
+ } else if (node.kind === "dict") {
62683
+ yield encoder.encode("<<\n");
62684
+ for (const entry of node.entries) {
62685
+ yield* serializeCosNodeChunks(entry.key, { signal });
62686
+ yield encoder.encode(" ");
62687
+ yield* serialized(entry.value);
62688
+ yield encoder.encode("\n");
62689
+ }
62690
+ yield encoder.encode(">>");
62691
+ } else if (node.kind === "array") {
62692
+ yield encoder.encode("[ ");
62693
+ for (const item of node.items) {
62694
+ yield* serialized(item);
62695
+ yield encoder.encode(" ");
62696
+ }
62697
+ yield encoder.encode("]");
62698
+ } else yield* serializeCosNodeChunks(node, { signal });
62699
+ }
62700
+ for (const edited of [owner, ...pageOwner && count ? [pageOwner] : []]) {
62701
+ let length = 0;
62702
+ for await (const bytes of serialized(edited.value)) length += bytes.length;
62703
+ await target.setSerializedValue({ objectNumber: edited.reference.objectNumber, generationNumber: edited.reference.generationNumber, body: { length, chunks: serialized(edited.value) } });
62704
+ }
62705
+ } catch (error) {
62706
+ failed = true;
62707
+ throw error;
62708
+ } finally {
62709
+ await appended.close().catch((error) => {
62710
+ if (!failed) throw error;
62711
+ });
62712
+ }
62713
+ }
62714
+
62021
62715
  // packages/pdf-ast/src/edit/retained-form-appearances.ts
62022
- import { IntegerTable as IntegerTable8, PagedStorage as PagedStorage13 } from "@poe-platform/safe-fs/storage";
62716
+ import { IntegerTable as IntegerTable8, PagedStorage as PagedStorage15 } from "@poe-platform/safe-fs/storage";
62023
62717
 
62024
62718
  // packages/pdf-ast/src/edit/form-appearance-chunks.ts
62025
62719
  function* serializeFormAppearanceChunks(text, options) {
@@ -62105,10 +62799,11 @@ function* operators(text, options) {
62105
62799
  }
62106
62800
 
62107
62801
  // packages/pdf-ast/src/edit/retained-form-appearances.ts
62108
- async function generateRetainedFormAppearances(document2, store, storage, signal) {
62802
+ async function generateRetainedFormAppearances(document2, store, storage, signal, update) {
62109
62803
  if (!document2.crossReference.rootRef) return;
62110
- const backing = new PagedStorage13({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), active = new IntegerTable8(backing);
62804
+ const backing = new PagedStorage15({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), active = new IntegerTable8(backing);
62111
62805
  let head = -1, failed = false, work = 0;
62806
+ let matched = false;
62112
62807
  let defaultAppearance;
62113
62808
  async function checkpoint(depth = 0) {
62114
62809
  signal.throwIfAborted();
@@ -62210,14 +62905,30 @@ async function generateRetainedFormAppearances(document2, store, storage, signal
62210
62905
  return "Yes";
62211
62906
  }
62212
62907
  try {
62213
- const form = await locate(formLocation);
62908
+ let form = await locate(formLocation);
62909
+ if (update && form?.value.kind !== "dict") {
62910
+ const catalog = await locate(root);
62911
+ if (catalog?.value.kind !== "dict") return;
62912
+ dictSet(catalog.value, "AcroForm", await store.allocate(cosDict({ Fields: cosArray([]), NeedAppearances: cosBool(true) })));
62913
+ await store.set(catalog.owner);
62914
+ form = await locate(formLocation);
62915
+ }
62214
62916
  if (form?.value.kind !== "dict") return;
62917
+ if (update) {
62918
+ dictSet(form.value, "NeedAppearances", cosBool(true));
62919
+ await store.set(form.owner);
62920
+ const fields3 = await locate(child(form.location, "Fields"));
62921
+ if (fields3?.value.kind !== "array") {
62922
+ dictSet(form.value, "Fields", cosArray([]));
62923
+ await store.set(form.owner);
62924
+ }
62925
+ }
62215
62926
  defaultAppearance = dictGet(form.value, "DA");
62216
62927
  const need = await resolve2(dictGet(form.value, "NeedAppearances")), force = need?.kind === "boolean" && need.value;
62217
62928
  const fields2 = await locate(child(form.location, "Fields"));
62218
62929
  if (fields2?.value.kind === "array") for (let i = fields2.value.items.length - 1; i >= 0; i--) {
62219
62930
  await checkpoint();
62220
- await push({ location: itemLocation(fields2.location, i, fields2.value.items[i]), named: false, ft: "", ff: 0, q: 0, depth: 0 });
62931
+ await push({ location: itemLocation(fields2.location, i, fields2.value.items[i]), named: "", ft: "", ff: 0, q: 0, depth: 0 });
62221
62932
  }
62222
62933
  while (head !== -1) {
62223
62934
  const record = await readStoredRecord(backing, head, signal);
@@ -62237,7 +62948,8 @@ async function generateRetainedFormAppearances(document2, store, storage, signal
62237
62948
  await push({ exit: id });
62238
62949
  }
62239
62950
  const name = await resolve2(dictGet(field2.value, "T")), ft = await resolve2(dictGet(field2.value, "FT"));
62240
- const named = frame.named || (name?.kind === "name" ? !!name.decoded : name?.kind === "string" ? !!decodePdfString(name) : false);
62951
+ const partial = name?.kind === "name" ? name.decoded : name?.kind === "string" ? decodePdfString(name) : "";
62952
+ const named = update ? frame.named && partial ? `${frame.named}.${partial}` : partial || frame.named : frame.named || partial ? "1" : "";
62241
62953
  const inherited = { ...frame, named, ft: ft?.kind === "name" ? ft.decoded : frame.ft, ff: await number(dictGet(field2.value, "Ff"), frame.ff), q: await number(dictGet(field2.value, "Q"), frame.q) };
62242
62954
  const maxLen = await resolve2(dictGet(field2.value, "MaxLen"));
62243
62955
  if (maxLen?.kind === "number") inherited.maxLen = maxLen.value;
@@ -62261,6 +62973,70 @@ async function generateRetainedFormAppearances(document2, store, storage, signal
62261
62973
  }
62262
62974
  }
62263
62975
  if (!named) continue;
62976
+ if (update) {
62977
+ if (named !== update.name) continue;
62978
+ matched = true;
62979
+ const value2 = update.value;
62980
+ if (typeof value2 === "boolean" || inherited.ft === "Btn") {
62981
+ const on = await onValue(field2.location);
62982
+ const checked = typeof value2 === "boolean" ? value2 : value2 !== "Off" && value2 !== "false" && value2 !== "0" && value2 !== "";
62983
+ const chosen = typeof value2 === "string" && value2 !== "true" && value2 !== "false" && value2 !== "Off" ? value2 : on;
62984
+ const state = cosName(checked ? chosen : "Off");
62985
+ dictSet(field2.value, "FT", cosName("Btn"));
62986
+ dictSet(field2.value, "V", state);
62987
+ dictSet(field2.value, "AS", state);
62988
+ await store.set(field2.owner);
62989
+ if (kids?.value.kind === "array") for (let i = 0; i < kids.value.items.length; i++) {
62990
+ await checkpoint();
62991
+ const kid = await locate(itemLocation(kids.location, i, kids.value.items[i]));
62992
+ if (kid?.value.kind !== "dict") continue;
62993
+ const normal = await locate(child(child(kid.location, "AP"), "N"));
62994
+ const selected2 = normal?.value.kind === "dict" && normal.value.entries.length ? cosName(checked && dictGet(normal.value, chosen) !== void 0 ? chosen : "Off") : state;
62995
+ dictSet(kid.value, "AS", selected2);
62996
+ await store.set(kid.owner);
62997
+ }
62998
+ continue;
62999
+ }
63000
+ if (!inherited.ft) dictSet(field2.value, "FT", cosName("Tx"));
63001
+ let text2 = String(value2);
63002
+ const multi = inherited.ft === "Ch" && !!(inherited.ff & 1 << 21) && text2.includes(",");
63003
+ const selected = multi ? text2.split(",").map((value3) => value3.trim()).filter(Boolean) : [text2];
63004
+ dictSet(field2.value, "V", multi ? cosArray(selected.map((value3) => cosString(value3))) : cosString(text2));
63005
+ if (inherited.ft === "Ch") {
63006
+ const choices = await resolve2(dictGet(field2.value, "Opt")), indices = [];
63007
+ if (choices?.kind === "array") for (let i = 0; i < choices.items.length; i++) {
63008
+ await checkpoint();
63009
+ const option = await resolve2(choices.items[i]);
63010
+ let exported = "", label = "", valid = false;
63011
+ if (option?.kind === "string") {
63012
+ exported = decodePdfString(option);
63013
+ label = exported;
63014
+ valid = true;
63015
+ } else if (option?.kind === "array" && option.items.length >= 2) {
63016
+ const first = await resolve2(option.items[0]), second = await resolve2(option.items[1]);
63017
+ exported = first?.kind === "string" ? decodePdfString(first) : "";
63018
+ label = second?.kind === "string" ? decodePdfString(second) : "";
63019
+ valid = true;
63020
+ }
63021
+ if (valid && (selected.includes(exported) || selected.includes(label))) {
63022
+ indices.push(i);
63023
+ if (!multi) {
63024
+ if (label) text2 = label;
63025
+ break;
63026
+ }
63027
+ }
63028
+ }
63029
+ if (indices.length) dictSet(field2.value, "I", cosArray(indices.map((value3) => cosNumber(value3))));
63030
+ }
63031
+ await store.set(field2.owner);
63032
+ await synthesize(field2.location, text2, inherited);
63033
+ if (kids?.value.kind === "array") for (let i = 0; i < kids.value.items.length; i++) {
63034
+ await checkpoint();
63035
+ const kid = await locate(itemLocation(kids.location, i, kids.value.items[i]));
63036
+ if (kid?.value.kind === "dict" && !dictGet(kid.value, "T")) await synthesize(kid.location, text2, inherited);
63037
+ }
63038
+ continue;
63039
+ }
62264
63040
  const value = await resolve2(dictGet(field2.value, "V"));
62265
63041
  if (!value) continue;
62266
63042
  const appearance = await resolve2(dictGet(field2.value, "AP")), hasNormal = appearance?.kind === "dict" && dictGet(appearance, "N") !== void 0;
@@ -62298,9 +63074,18 @@ async function generateRetainedFormAppearances(document2, store, storage, signal
62298
63074
  if (kid?.value.kind === "dict" && !dictGet(kid.value, "T")) await synthesize(kid.location, text, inherited);
62299
63075
  }
62300
63076
  }
63077
+ if (update && !matched) {
63078
+ const fields3 = await locate(child(formLocation, "Fields"));
63079
+ if (fields3?.value.kind === "array") {
63080
+ const value = update.value;
63081
+ const field2 = typeof value === "boolean" ? cosDict({ FT: cosName("Btn"), T: cosString(update.name), V: cosName(value ? "Yes" : "Off"), AS: cosName(value ? "Yes" : "Off") }) : cosDict({ FT: cosName("Tx"), T: cosString(update.name), V: cosString(value) });
63082
+ fields3.value.items.push(await store.allocate(field2));
63083
+ await store.set(fields3.owner);
63084
+ }
63085
+ }
62301
63086
  const latest = await locate(formLocation);
62302
63087
  if (latest?.value.kind === "dict") {
62303
- dictSet(latest.value, "NeedAppearances", cosBool(false));
63088
+ dictSet(latest.value, "NeedAppearances", cosBool(!!update));
62304
63089
  await store.set(latest.owner);
62305
63090
  }
62306
63091
  } catch (error) {
@@ -62314,16 +63099,16 @@ async function generateRetainedFormAppearances(document2, store, storage, signal
62314
63099
  }
62315
63100
 
62316
63101
  // packages/pdf-ast/src/edit/retained-flatten-annotations.ts
62317
- import { IntegerTable as IntegerTable10, PagedStorage as PagedStorage17 } from "@poe-platform/safe-fs/storage";
63102
+ import { IntegerTable as IntegerTable10, PagedStorage as PagedStorage19 } from "@poe-platform/safe-fs/storage";
62318
63103
 
62319
63104
  // packages/pdf-ast/src/edit/retained-content-edit.ts
62320
- import { IntegerTable as IntegerTable9, PagedStorage as PagedStorage14 } from "@poe-platform/safe-fs/storage";
63105
+ import { IntegerTable as IntegerTable9, PagedStorage as PagedStorage16 } from "@poe-platform/safe-fs/storage";
62321
63106
  var RetainedContentEditor = class _RetainedContentEditor {
62322
63107
  constructor(store, storage, signal) {
62323
63108
  this.store = store;
62324
63109
  this.storage = storage;
62325
63110
  this.signal = signal;
62326
- this.backing = new PagedStorage14({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63111
+ this.backing = new PagedStorage16({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62327
63112
  this.counts = new IntegerTable9(this.backing);
62328
63113
  this.identities = new PdfNameIndex(storage, Infinity, signal);
62329
63114
  }
@@ -62364,6 +63149,12 @@ var RetainedContentEditor = class _RetainedContentEditor {
62364
63149
  await this.count(value, 1n);
62365
63150
  await this.store.set({ objectNumber: reference.objectNumber, generationNumber: reference.generationNumber, value, ...stream ? { stream } : {} });
62366
63151
  }
63152
+ async setSerialized(reference, body, values) {
63153
+ const old = await this.store.get(reference.objectNumber);
63154
+ if (old) await this.count(old.value, -1n);
63155
+ for await (const node of values) await this.count(node, 1n);
63156
+ await this.store.setSerializedValue({ objectNumber: reference.objectNumber, generationNumber: reference.generationNumber, body });
63157
+ }
62367
63158
  async replace(page2, chunks, compress = true) {
62368
63159
  const source = compress ? await stageDeflatedPdf(chunks, this.storage, this.signal) : await PdfFileSource.fromStream(this.storage.fs, this.storage.directory, chunks, { signal: this.signal });
62369
63160
  let failed = false;
@@ -62389,14 +63180,14 @@ var RetainedContentEditor = class _RetainedContentEditor {
62389
63180
  };
62390
63181
 
62391
63182
  // packages/pdf-ast/src/edit/retained-name-replacement.ts
62392
- import { PagedStorage as PagedStorage15 } from "@poe-platform/safe-fs/storage";
63183
+ import { PagedStorage as PagedStorage17 } from "@poe-platform/safe-fs/storage";
62393
63184
  async function* replaceRetainedPdfName(input, oldName, newName, storage, options = {}) {
62394
63185
  const chunkBytes = options.chunkBytes ?? 16384, maximum10 = options.maxOutputBytes ?? Infinity;
62395
63186
  if (!Number.isSafeInteger(chunkBytes) || chunkBytes < 1) throw new RangeError("Invalid name replacement chunk size");
62396
63187
  if (maximum10 !== Infinity && (!Number.isSafeInteger(maximum10) || maximum10 < 0)) throw new RangeError("Invalid name replacement output limit");
62397
63188
  const signal = options.signal ?? new AbortController().signal;
62398
63189
  signal.throwIfAborted();
62399
- const table = new PagedStorage15({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), length = oldName.length + 1;
63190
+ const table = new PagedStorage17({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), length = oldName.length + 1;
62400
63191
  const base = table.allocate(length * 8), record = new Uint8Array(8), view = new DataView(record.buffer);
62401
63192
  const pattern = (at) => at ? oldName.charCodeAt(at - 1) : 47;
62402
63193
  let buffer = new Uint8Array(chunkBytes), used = 0, total = 0, work = 0, failed = false;
@@ -62474,10 +63265,10 @@ async function* replaceRetainedPdfName(input, oldName, newName, storage, options
62474
63265
  }
62475
63266
 
62476
63267
  // packages/pdf-ast/src/edit/retained-draw-text.ts
62477
- import { PagedStorage as PagedStorage16 } from "@poe-platform/safe-fs/storage";
63268
+ import { PagedStorage as PagedStorage18 } from "@poe-platform/safe-fs/storage";
62478
63269
  async function drawRetainedAnnotationText(page2, editor, storage, text, x, y, isolated, font, signal) {
62479
63270
  const source = await PdfFileSource.fromStream(storage.fs, storage.directory, page2.streamContents(), { signal });
62480
- const backing = new PagedStorage16({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63271
+ const backing = new PagedStorage18({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62481
63272
  let failed = false;
62482
63273
  try {
62483
63274
  const name = await font(), position = backing.allocate(text.length);
@@ -62553,7 +63344,7 @@ async function flattenRetainedAnnotations(document2, store, storage, mode, signa
62553
63344
  for await (const page2 of document2.pages()) {
62554
63345
  const annotations = await array(dictGet(page2.dict, "Annots"));
62555
63346
  if (!annotations) continue;
62556
- const survivorStorage = new PagedStorage17({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63347
+ const survivorStorage = new PagedStorage19({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62557
63348
  const survivorBase = survivorStorage.allocate(0);
62558
63349
  let pageFailed = false;
62559
63350
  try {
@@ -62639,7 +63430,7 @@ async function flattenRetainedAnnotations(document2, store, storage, mode, signa
62639
63430
  }
62640
63431
  if (normal?.stream && normal.reference && normal.value.kind === "dict") {
62641
63432
  let content = await PdfFileSource.fromStream(storage.fs, storage.directory, document2.objects.decodeStream(normal.reference.objectNumber, normal.reference.generationNumber), { signal });
62642
- const backing = new PagedStorage17({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), renames = new IntegerTable10(backing), names = new PdfNameIndex(storage, Infinity, signal);
63433
+ const backing = new PagedStorage19({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), renames = new IntegerTable10(backing), names = new PdfNameIndex(storage, Infinity, signal);
62643
63434
  let appearanceFailed = false, count = 0;
62644
63435
  try {
62645
63436
  if (content.size) {
@@ -62757,8 +63548,294 @@ q ${scaleX} 0 0 ${scaleY} ${tx} ${ty} cm${matSuffix}
62757
63548
  }
62758
63549
  }
62759
63550
 
63551
+ // packages/pdf-ast/src/edit/retained-name-map.ts
63552
+ import { PagedStorage as PagedStorage20 } from "@poe-platform/safe-fs/storage";
63553
+ async function* replaceRetainedPdfNames(input, names, storage, options = {}) {
63554
+ const signal = options.signal ?? new AbortController().signal, size = options.chunkBytes ?? 16384;
63555
+ if (!Number.isSafeInteger(size) || size < 1) throw new RangeError("Invalid name replacement chunk size");
63556
+ const trie = new PagedStorage20({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), pending = new PagedStorage20({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63557
+ const root = trie.allocate(40), prefixBase = pending.allocate(0);
63558
+ let output = new Uint8Array(size), used = 0, failed = false, work = 0;
63559
+ const body = (byte3) => byte3 >= 48 && byte3 <= 57 || byte3 >= 65 && byte3 <= 90 || byte3 >= 97 && byte3 <= 122 || [95, 46, 43, 45].includes(byte3);
63560
+ async function checkpoint() {
63561
+ signal.throwIfAborted();
63562
+ if (++work % 16384 === 0) await new Promise((resolve2) => setTimeout(resolve2, 0));
63563
+ }
63564
+ async function get(at) {
63565
+ const bytes = await trie.read(at, 40);
63566
+ return new DataView(bytes.buffer, bytes.byteOffset, bytes.length);
63567
+ }
63568
+ async function put(at, row) {
63569
+ await trie.write(at, new Uint8Array(row.buffer, row.byteOffset, row.byteLength));
63570
+ }
63571
+ async function child(at, byte3, create) {
63572
+ const parent = await get(at);
63573
+ let current = parent.getFloat64(0);
63574
+ while (current) {
63575
+ const row2 = await get(current);
63576
+ if (row2.getFloat64(16) === byte3) return current;
63577
+ current = row2.getFloat64(8);
63578
+ }
63579
+ if (!create) return;
63580
+ const next = trie.allocate(40), row = new DataView(new ArrayBuffer(40));
63581
+ row.setFloat64(8, parent.getFloat64(0));
63582
+ row.setFloat64(16, byte3);
63583
+ await put(next, row);
63584
+ parent.setFloat64(0, next);
63585
+ await put(at, parent);
63586
+ return next;
63587
+ }
63588
+ function emit(byte3) {
63589
+ output[used++] = byte3;
63590
+ if (used === size) {
63591
+ const full = output;
63592
+ output = new Uint8Array(size);
63593
+ used = 0;
63594
+ return full;
63595
+ }
63596
+ }
63597
+ async function* replay(store, start, length) {
63598
+ for (let at = 0; at < length; at += size) for (const byte3 of await store.read(start + at, Math.min(size, length - at))) {
63599
+ await checkpoint();
63600
+ const full = emit(byte3);
63601
+ if (full) yield full;
63602
+ }
63603
+ }
63604
+ try {
63605
+ for await (const [name, replacement] of names) {
63606
+ let node2 = root, valid = true;
63607
+ for (let i = 0; i < name.length; i++) {
63608
+ await checkpoint();
63609
+ if (!body(name.charCodeAt(i))) {
63610
+ valid = false;
63611
+ break;
63612
+ }
63613
+ node2 = await child(node2, name.charCodeAt(i), true);
63614
+ }
63615
+ if (!valid) continue;
63616
+ const start = trie.allocate(replacement.length), row = await get(node2);
63617
+ row.setFloat64(24, start + 1);
63618
+ row.setFloat64(32, replacement.length);
63619
+ await put(node2, row);
63620
+ for (let at = 0; at < replacement.length; at += size) {
63621
+ const bytes = new Uint8Array(Math.min(size, replacement.length - at));
63622
+ for (let i = 0; i < bytes.length; i++) bytes[i] = replacement.charCodeAt(at + i);
63623
+ await trie.write(start + at, bytes);
63624
+ }
63625
+ }
63626
+ let matching = false, node = root, length = 0, capacity = 0, buffered = 0;
63627
+ const prefix = new Uint8Array(size);
63628
+ async function flushPrefix() {
63629
+ if (buffered) {
63630
+ if (length > capacity) {
63631
+ pending.allocate(length - capacity);
63632
+ capacity = length;
63633
+ }
63634
+ await pending.write(prefixBase + length - buffered, prefix.subarray(0, buffered));
63635
+ buffered = 0;
63636
+ }
63637
+ }
63638
+ async function* finish() {
63639
+ await flushPrefix();
63640
+ const row = await get(node), replacement = row.getFloat64(24);
63641
+ const slash = emit(47);
63642
+ if (slash) yield slash;
63643
+ if (replacement) yield* replay(trie, replacement - 1, row.getFloat64(32));
63644
+ else yield* replay(pending, prefixBase, length);
63645
+ matching = false;
63646
+ }
63647
+ for await (const bytes of input) for (const byte3 of bytes) {
63648
+ await checkpoint();
63649
+ if (matching && body(byte3)) {
63650
+ const next = await child(node, byte3, false);
63651
+ if (next !== void 0) {
63652
+ node = next;
63653
+ prefix[buffered++] = byte3;
63654
+ length++;
63655
+ if (buffered === size) await flushPrefix();
63656
+ continue;
63657
+ }
63658
+ await flushPrefix();
63659
+ const slash = emit(47);
63660
+ if (slash) yield slash;
63661
+ yield* replay(pending, prefixBase, length);
63662
+ matching = false;
63663
+ } else if (matching) yield* finish();
63664
+ if (byte3 === 47) {
63665
+ matching = true;
63666
+ node = root;
63667
+ length = 0;
63668
+ buffered = 0;
63669
+ } else {
63670
+ const full = emit(byte3);
63671
+ if (full) yield full;
63672
+ }
63673
+ }
63674
+ if (matching) yield* finish();
63675
+ if (used) yield output.subarray(0, used);
63676
+ } catch (error) {
63677
+ failed = true;
63678
+ throw error;
63679
+ } finally {
63680
+ const results = await Promise.allSettled([trie.close(), pending.close()]);
63681
+ if (!failed) {
63682
+ for (const result of results) if (result.status === "rejected") await Promise.reject(result.reason);
63683
+ }
63684
+ }
63685
+ }
63686
+
63687
+ // packages/pdf-ast/src/edit/retained-preserve-stamp.ts
63688
+ async function preserveRetainedStamp(document2, source, page2, other, store, editor, storage, clone, mode, signal) {
63689
+ const renames = new PdfMutableObjectStore(storage, { signal }), additions = new PdfMutableObjectStore(storage, { signal });
63690
+ let addedCount = 0, count = 0, failed = false, work = 0;
63691
+ const owners = /* @__PURE__ */ new Map();
63692
+ const key = (ref) => `${ref.objectNumber}:${ref.generationNumber}`;
63693
+ if (page2.reference) owners.set(key(page2.reference), { reference: page2.reference, value: page2.dict });
63694
+ async function checkpoint() {
63695
+ signal.throwIfAborted();
63696
+ if (++work % 64 === 0) await new Promise((resolve2) => setTimeout(resolve2, 0));
63697
+ }
63698
+ async function dictionary(node) {
63699
+ const cached = node?.kind === "ref" ? owners.get(key(node)) : void 0;
63700
+ if (cached) return cached;
63701
+ const found = await document2.lookup(node);
63702
+ if (found?.stream || found?.value.kind !== "dict") return;
63703
+ const result = { ...found, value: found.value };
63704
+ if (result.reference) owners.set(key(result.reference), { reference: result.reference, value: result.value });
63705
+ return result;
63706
+ }
63707
+ async function stream(chunks) {
63708
+ const staged = await PdfFileSource.fromStream(storage.fs, storage.directory, chunks, { signal });
63709
+ let failed2 = false;
63710
+ try {
63711
+ const reference = await store.allocate();
63712
+ await editor.set(reference, cosDict({ Length: cosNumber(staged.size) }), { decoded: true, length: staged.size, chunks: staged.stream(0, staged.size, signal) });
63713
+ return reference;
63714
+ } catch (error) {
63715
+ failed2 = true;
63716
+ throw error;
63717
+ } finally {
63718
+ await staged.close().catch((error) => {
63719
+ if (!failed2) throw error;
63720
+ });
63721
+ }
63722
+ }
63723
+ async function* mappings() {
63724
+ for await (const object of renames.objects()) if (object.value.kind === "array" && object.value.items[0]?.kind === "string" && object.value.items[1]?.kind === "string") {
63725
+ const [name, replacement] = object.value.items;
63726
+ yield [decodePdfString(name), decodePdfString(replacement)];
63727
+ }
63728
+ }
63729
+ try {
63730
+ const dstAttributes = await page2.attributes(), srcAttributes = await other.attributes();
63731
+ let resources = await dictionary(dictGet(page2.dict, "Resources"));
63732
+ if (!resources) {
63733
+ const entries = [];
63734
+ for (const entry of dstAttributes.resources.entries) {
63735
+ const sub = await document2.lookup(entry.value);
63736
+ entries.push({ key: { ...entry.key }, value: sub?.value.kind === "dict" && !sub.stream ? cosDict(Object.fromEntries(sub.value.entries.map((item) => [item.key.decoded, item.value]))) : entry.value });
63737
+ }
63738
+ resources = { value: { kind: "dict", entries } };
63739
+ dictSet(page2.dict, "Resources", resources.value);
63740
+ }
63741
+ for (const category of ["Font", "XObject", "ExtGState", "ColorSpace", "Pattern", "Shading", "Properties"]) {
63742
+ const src = await source.lookup(dictGet(srcAttributes.resources, category));
63743
+ if (src?.stream || src?.value.kind !== "dict") continue;
63744
+ let dst = await dictionary(dictGet(resources.value, category));
63745
+ if (!dst) {
63746
+ dst = { value: cosDict({}) };
63747
+ dictSet(resources.value, category, dst.value);
63748
+ }
63749
+ for (const entry of src.value.entries) {
63750
+ await checkpoint();
63751
+ const value = await clone(entry.value), original = entry.key.decoded;
63752
+ let name = original;
63753
+ if (dictGet(dst.value, original)) {
63754
+ name = `Ov_${page2.index}_${original}`;
63755
+ let suffix = 1;
63756
+ while (dictGet(dst.value, name)) {
63757
+ await checkpoint();
63758
+ name = `Ov_${page2.index}_${suffix++}_${original}`;
63759
+ }
63760
+ await renames.set({ objectNumber: ++count, generationNumber: 0, value: cosArray([cosString(original), cosString(name)]) });
63761
+ }
63762
+ dictSet(dst.value, name, value);
63763
+ }
63764
+ }
63765
+ for (const owner of owners.values()) await editor.set(owner.reference, owner.value);
63766
+ const contents = dictGet(other.dict, "Contents");
63767
+ if (!contents) return;
63768
+ const resolved = await source.lookup(contents), nodes = resolved?.value.kind === "array" && !resolved.stream ? resolved.value.items : [contents];
63769
+ for (const node of nodes) {
63770
+ await checkpoint();
63771
+ const found = await source.lookup(node);
63772
+ const added = found?.stream && found.reference && count ? await stream(replaceRetainedPdfNames(source.objects.decodeStream(found.reference.objectNumber, found.reference.generationNumber), mappings(), storage, { signal })) : await clone(node);
63773
+ await additions.set({ objectNumber: ++addedCount, generationNumber: 0, value: added });
63774
+ }
63775
+ if (!addedCount) return;
63776
+ const previous = dictGet(page2.dict, "Contents"), resolvedPrevious = previous && await document2.lookup(previous);
63777
+ const before = resolvedPrevious?.value.kind === "array" && !resolvedPrevious.stream ? resolvedPrevious.value.items : previous ? [previous] : [];
63778
+ const encoder = new TextEncoder();
63779
+ async function* text(value) {
63780
+ yield encoder.encode(value);
63781
+ }
63782
+ const openTarget = await stream(text("q\n")), openSource = await stream(text(retainedStampTransform(dstAttributes, srcAttributes))), close = await stream(text("\nQ\n"));
63783
+ const marker2 = cosArray([]);
63784
+ dictSet(page2.dict, "Contents", marker2);
63785
+ async function* contentNodes() {
63786
+ for (const overlay of mode === "underlay" ? [true, false] : [false, true]) {
63787
+ yield overlay ? openSource : openTarget;
63788
+ if (overlay) {
63789
+ for await (const object of additions.objects()) {
63790
+ await checkpoint();
63791
+ yield object.value;
63792
+ }
63793
+ } else for (const node of before) {
63794
+ await checkpoint();
63795
+ yield node;
63796
+ }
63797
+ yield close;
63798
+ }
63799
+ }
63800
+ async function* body() {
63801
+ yield encoder.encode("<<\n");
63802
+ for (const entry of page2.dict.entries) {
63803
+ yield* serializeCosNodeChunks(entry.key, { signal });
63804
+ yield encoder.encode(" ");
63805
+ if (entry.value === marker2) {
63806
+ yield encoder.encode("[ ");
63807
+ for await (const node of contentNodes()) {
63808
+ yield* serializeCosNodeChunks(node, { signal });
63809
+ yield encoder.encode(" ");
63810
+ }
63811
+ yield encoder.encode("]");
63812
+ } else yield* serializeCosNodeChunks(entry.value, { signal });
63813
+ yield encoder.encode("\n");
63814
+ }
63815
+ yield encoder.encode(">>");
63816
+ }
63817
+ async function* values() {
63818
+ yield page2.dict;
63819
+ yield* contentNodes();
63820
+ }
63821
+ if (page2.reference) {
63822
+ let length = 0;
63823
+ for await (const bytes of body()) length += bytes.length;
63824
+ await editor.setSerialized(page2.reference, { length, chunks: body() }, values());
63825
+ }
63826
+ } catch (error) {
63827
+ failed = true;
63828
+ throw error;
63829
+ } finally {
63830
+ const results = await Promise.allSettled([renames.close(), additions.close()]);
63831
+ if (!failed) {
63832
+ for (const result of results) if (result.status === "rejected") await Promise.reject(result.reason);
63833
+ }
63834
+ }
63835
+ }
63836
+
62760
63837
  // packages/pdf-ast/src/edit/retained-stamps.ts
62761
- import { IntegerTable as IntegerTable11, PagedStorage as PagedStorage18 } from "@poe-platform/safe-fs/storage";
63838
+ import { IntegerTable as IntegerTable11, PagedStorage as PagedStorage21 } from "@poe-platform/safe-fs/storage";
62762
63839
  async function stampRetainedPages(document2, store, storage, getPage, stamps, signal) {
62763
63840
  const editor = await RetainedContentEditor.open(store, storage, signal);
62764
63841
  let counter = 1, failed = false, work = 0;
@@ -62769,7 +63846,7 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62769
63846
  try {
62770
63847
  for await (const stamp of stamps) {
62771
63848
  const source = await editRetainedDocument(stamp.source, storage, { signal });
62772
- const backing = new PagedStorage18({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), memo = new IntegerTable11(backing);
63849
+ const backing = new PagedStorage21({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), memo = new IntegerTable11(backing);
62773
63850
  let stampFailed = false;
62774
63851
  async function clone(node, depth = 0) {
62775
63852
  await checkpoint();
@@ -62779,7 +63856,12 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62779
63856
  if (found !== void 0) return cosRef(Number(found));
62780
63857
  const identity = await source.document.crossReference.index.get(node.objectNumber, signal);
62781
63858
  const object = identity ? await source.document.objects.get(node.objectNumber, identity.generationNumber ?? 0) : void 0;
62782
- if (!object) return { kind: "null" };
63859
+ if (!object) {
63860
+ if (!stamp.preserveStreams) return { kind: "null" };
63861
+ const reference2 = await store.allocate(cosDict({}));
63862
+ await memo.set(BigInt(node.objectNumber), BigInt(reference2.objectNumber));
63863
+ return reference2;
63864
+ }
62783
63865
  const reference = await store.allocate({ kind: "null" });
62784
63866
  await memo.set(BigInt(node.objectNumber), BigInt(reference.objectNumber));
62785
63867
  const value = await clone(object.value, depth + 1);
@@ -62798,6 +63880,11 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62798
63880
  if (node.kind === "dict") {
62799
63881
  const entries = [];
62800
63882
  for (const entry of node.entries) if (entry.key.decoded !== "Parent") entries.push({ key: { ...entry.key }, value: await clone(entry.value, depth + 1) });
63883
+ if (stamp.preserveStreams) {
63884
+ const dict = cosDict({});
63885
+ for (const entry of entries) dictSet(dict, entry.key.decoded, entry.value);
63886
+ return dict;
63887
+ }
62801
63888
  return { kind: "dict", entries };
62802
63889
  }
62803
63890
  return node;
@@ -62806,6 +63893,10 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62806
63893
  for await (const pair of stamp.pages) {
62807
63894
  await checkpoint();
62808
63895
  const page2 = await getPage(pair.targetIndex), other = await source.getPage(pair.sourceIndex);
63896
+ if (stamp.preserveStreams) {
63897
+ await preserveRetainedStamp(document2, source.document, page2, other, store, editor, storage, clone, stamp.mode, signal);
63898
+ continue;
63899
+ }
62809
63900
  const target = await PdfFileSource.fromStream(storage.fs, storage.directory, page2.streamContents(), { signal });
62810
63901
  let content, pageFailed = false;
62811
63902
  try {
@@ -62859,43 +63950,7 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62859
63950
  }
62860
63951
  }
62861
63952
  for (const owner of owners.values()) await editor.set(owner.reference, owner.value);
62862
- const dstSize = { width: Math.abs(dstAttributes.mediaBox[2] - dstAttributes.mediaBox[0]), height: Math.abs(dstAttributes.mediaBox[3] - dstAttributes.mediaBox[1]) };
62863
- const srcSize = { width: Math.abs(srcAttributes.mediaBox[2] - srcAttributes.mediaBox[0]), height: Math.abs(srcAttributes.mediaBox[3] - srcAttributes.mediaBox[1]) };
62864
- const rotDiff = ((dstAttributes.rotation - srcAttributes.rotation) % 360 + 360) % 360;
62865
- let stampOpenStr = "q\n";
62866
- if (srcSize.width > 0 && srcSize.height > 0) {
62867
- const fmt6 = (n) => Number(n.toFixed(6));
62868
- const fmt4 = (n) => Number(n.toFixed(4));
62869
- if (rotDiff === 90) {
62870
- const s = Math.min(dstSize.height / srcSize.width, dstSize.width / srcSize.height);
62871
- const ox = (dstSize.height - srcSize.width * s) / 2;
62872
- const oy = (dstSize.width - srcSize.height * s) / 2;
62873
- stampOpenStr = `q
62874
- 0 ${fmt6(s)} ${fmt6(-s)} 0 ${fmt4(dstSize.width - oy)} ${fmt4(ox)} cm
62875
- `;
62876
- } else if (rotDiff === 180) {
62877
- const s = Math.min(dstSize.width / srcSize.width, dstSize.height / srcSize.height);
62878
- const ox = (dstSize.width - srcSize.width * s) / 2;
62879
- const oy = (dstSize.height - srcSize.height * s) / 2;
62880
- stampOpenStr = `q
62881
- ${fmt6(-s)} 0 0 ${fmt6(-s)} ${fmt4(dstSize.width - ox)} ${fmt4(dstSize.height - oy)} cm
62882
- `;
62883
- } else if (rotDiff === 270) {
62884
- const s = Math.min(dstSize.height / srcSize.width, dstSize.width / srcSize.height);
62885
- const ox = (dstSize.height - srcSize.width * s) / 2;
62886
- const oy = (dstSize.width - srcSize.height * s) / 2;
62887
- stampOpenStr = `q
62888
- 0 ${fmt6(-s)} ${fmt6(s)} 0 ${fmt4(oy)} ${fmt4(dstSize.height - ox)} cm
62889
- `;
62890
- } else if (Math.abs(srcSize.width - dstSize.width) > 0.5 || Math.abs(srcSize.height - dstSize.height) > 0.5) {
62891
- const s = Math.min(dstSize.width / srcSize.width, dstSize.height / srcSize.height);
62892
- const tx = (dstSize.width - srcSize.width * s) / 2;
62893
- const ty = (dstSize.height - srcSize.height * s) / 2;
62894
- stampOpenStr = `q
62895
- ${fmt6(s)} 0 0 ${fmt6(s)} ${fmt4(tx)} ${fmt4(ty)} cm
62896
- `;
62897
- }
62898
- }
63953
+ const stampOpenStr = retainedStampTransform(dstAttributes, srcAttributes);
62899
63954
  const encoder = new TextEncoder(), stamped = content;
62900
63955
  async function* contents() {
62901
63956
  for (const isStamp of stamp.mode === "underlay" ? [true, false] : [false, true]) {
@@ -62935,14 +63990,54 @@ ${fmt6(s)} 0 0 ${fmt6(s)} ${fmt4(tx)} ${fmt4(ty)} cm
62935
63990
  });
62936
63991
  }
62937
63992
  }
63993
+ function retainedStampTransform(dstAttributes, srcAttributes) {
63994
+ const dstSize = { width: Math.abs(dstAttributes.mediaBox[2] - dstAttributes.mediaBox[0]), height: Math.abs(dstAttributes.mediaBox[3] - dstAttributes.mediaBox[1]) };
63995
+ const srcSize = { width: Math.abs(srcAttributes.mediaBox[2] - srcAttributes.mediaBox[0]), height: Math.abs(srcAttributes.mediaBox[3] - srcAttributes.mediaBox[1]) };
63996
+ const rotDiff = ((dstAttributes.rotation - srcAttributes.rotation) % 360 + 360) % 360;
63997
+ let stampOpenStr = "q\n";
63998
+ if (srcSize.width > 0 && srcSize.height > 0) {
63999
+ const fmt6 = (n) => Number(n.toFixed(6));
64000
+ const fmt4 = (n) => Number(n.toFixed(4));
64001
+ if (rotDiff === 90) {
64002
+ const s = Math.min(dstSize.height / srcSize.width, dstSize.width / srcSize.height);
64003
+ const ox = (dstSize.height - srcSize.width * s) / 2;
64004
+ const oy = (dstSize.width - srcSize.height * s) / 2;
64005
+ stampOpenStr = `q
64006
+ 0 ${fmt6(s)} ${fmt6(-s)} 0 ${fmt4(dstSize.width - oy)} ${fmt4(ox)} cm
64007
+ `;
64008
+ } else if (rotDiff === 180) {
64009
+ const s = Math.min(dstSize.width / srcSize.width, dstSize.height / srcSize.height);
64010
+ const ox = (dstSize.width - srcSize.width * s) / 2;
64011
+ const oy = (dstSize.height - srcSize.height * s) / 2;
64012
+ stampOpenStr = `q
64013
+ ${fmt6(-s)} 0 0 ${fmt6(-s)} ${fmt4(dstSize.width - ox)} ${fmt4(dstSize.height - oy)} cm
64014
+ `;
64015
+ } else if (rotDiff === 270) {
64016
+ const s = Math.min(dstSize.height / srcSize.width, dstSize.width / srcSize.height);
64017
+ const ox = (dstSize.height - srcSize.width * s) / 2;
64018
+ const oy = (dstSize.width - srcSize.height * s) / 2;
64019
+ stampOpenStr = `q
64020
+ 0 ${fmt6(-s)} ${fmt6(s)} 0 ${fmt4(oy)} ${fmt4(dstSize.height - ox)} cm
64021
+ `;
64022
+ } else if (Math.abs(srcSize.width - dstSize.width) > 0.5 || Math.abs(srcSize.height - dstSize.height) > 0.5) {
64023
+ const s = Math.min(dstSize.width / srcSize.width, dstSize.height / srcSize.height);
64024
+ const tx = (dstSize.width - srcSize.width * s) / 2;
64025
+ const ty = (dstSize.height - srcSize.height * s) / 2;
64026
+ stampOpenStr = `q
64027
+ ${fmt6(s)} 0 0 ${fmt6(s)} ${fmt4(tx)} ${fmt4(ty)} cm
64028
+ `;
64029
+ }
64030
+ }
64031
+ return stampOpenStr;
64032
+ }
62938
64033
 
62939
64034
  // packages/pdf-ast/src/edit/retained-inline-images.ts
62940
- import { PagedStorage as PagedStorage19 } from "@poe-platform/safe-fs/storage";
64035
+ import { PagedStorage as PagedStorage22 } from "@poe-platform/safe-fs/storage";
62941
64036
  async function externalizeRetainedInlineImages(document2, store, storage, options, signal) {
62942
64037
  const minimum = options.minBytes ?? 1024;
62943
64038
  if (!Number.isSafeInteger(minimum) || minimum < 0) throw new RangeError("Invalid inline-image minimum size");
62944
64039
  const editor = await RetainedContentEditor.open(store, storage, signal);
62945
- const paths = new PagedStorage19({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
64040
+ const paths = new PagedStorage22({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62946
64041
  const keys = { BPC: "BitsPerComponent", CS: "ColorSpace", D: "Decode", DP: "DecodeParms", F: "Filter", H: "Height", IM: "ImageMask", I: "Interpolate", W: "Width" };
62947
64042
  const colors = { G: "DeviceGray", RGB: "DeviceRGB", CMYK: "DeviceCMYK", I: "Indexed" };
62948
64043
  const filters = { AHx: "ASCIIHexDecode", A85: "ASCII85Decode", LZW: "LZWDecode", Fl: "FlateDecode", RL: "RunLengthDecode", CCF: "CCITTFaxDecode", DCT: "DCTDecode" };
@@ -63034,7 +64129,7 @@ async function externalizeRetainedInlineImages(document2, store, storage, option
63034
64129
  }
63035
64130
 
63036
64131
  // packages/pdf-ast/src/edit/retained-resource-pruning.ts
63037
- import { IntegerTable as IntegerTable12, PagedStorage as PagedStorage20 } from "@poe-platform/safe-fs/storage";
64132
+ import { IntegerTable as IntegerTable12, PagedStorage as PagedStorage23 } from "@poe-platform/safe-fs/storage";
63038
64133
  async function collectNames(input, names, found, signal) {
63039
64134
  const iterator = input[Symbol.asyncIterator](), pending = [];
63040
64135
  let chunk = new Uint8Array(), at = 0, ended = false, changed = false, work = 0, failed = false;
@@ -63116,7 +64211,7 @@ async function pruneRetainedResources(document2, store, storage, signal) {
63116
64211
  return { ...found2, value: same(page2.reference) ? page2.dict : same(resources?.reference) ? resources.value : found2.value };
63117
64212
  }
63118
64213
  const names = new PdfNameIndex(storage, Infinity, signal), visitedNames = new PdfNameIndex(storage, Infinity, signal);
63119
- const backing = new PagedStorage20({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), found = new IntegerTable12(backing);
64214
+ const backing = new PagedStorage23({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), found = new IntegerTable12(backing);
63120
64215
  let failed = false;
63121
64216
  try {
63122
64217
  const referenced = async (name) => await found.get(BigInt((await names.intern(name)).index)) !== void 0;
@@ -63246,7 +64341,7 @@ async function flattenRetainedRotations(document2, store, storage, signal) {
63246
64341
  }
63247
64342
 
63248
64343
  // packages/pdf-ast/src/edit/retained-attachment-edits.ts
63249
- import { IntegerTable as IntegerTable13, PagedStorage as PagedStorage21 } from "@poe-platform/safe-fs/storage";
64344
+ import { IntegerTable as IntegerTable13, PagedStorage as PagedStorage24 } from "@poe-platform/safe-fs/storage";
63250
64345
  var PdfDuplicateAttachment = class extends PdfError {
63251
64346
  constructor(key) {
63252
64347
  super("E_CAPABILITY", `Duplicate attachment key: ${key}`);
@@ -63257,7 +64352,7 @@ var PdfDuplicateAttachment = class extends PdfError {
63257
64352
  async function editRetainedAttachments(document2, target, storage, remove, additions, signal, preserveTree = false) {
63258
64353
  const pairs = new PdfMutableObjectStore(storage, { signal });
63259
64354
  const names = new PdfNameIndex(storage, Infinity, signal), removed = new PdfNameIndex(storage, Infinity, signal);
63260
- const backing = new PagedStorage21({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), first = new IntegerTable13(backing), removals = new IntegerTable13(backing);
64355
+ const backing = new PagedStorage24({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), first = new IntegerTable13(backing), removals = new IntegerTable13(backing);
63261
64356
  let failed = false, count = 0, work = 0;
63262
64357
  async function checkpoint() {
63263
64358
  signal.throwIfAborted();
@@ -63459,13 +64554,13 @@ async function* retainedAttachmentNameTokens(document2, storage, root, signal, r
63459
64554
  }
63460
64555
 
63461
64556
  // packages/pdf-ast/src/edit/retained-graph.ts
63462
- import { PagedStorage as PagedStorage22 } from "@poe-platform/safe-fs/storage";
64557
+ import { PagedStorage as PagedStorage25 } from "@poe-platform/safe-fs/storage";
63463
64558
  async function editRetainedDocument(source, storage, options = {}) {
63464
64559
  if (options.maxPages !== void 0 && options.maxPages !== Infinity && (!Number.isSafeInteger(options.maxPages) || options.maxPages < 0)) throw new RangeError("Invalid page limit");
63465
64560
  if (options.maxRecursionDepth !== void 0 && options.maxRecursionDepth !== Infinity && (!Number.isSafeInteger(options.maxRecursionDepth) || options.maxRecursionDepth < 1)) throw new RangeError("Invalid edit depth");
63466
64561
  const signal = options.signal ?? new AbortController().signal;
63467
64562
  const store = new PdfMutableObjectStore(storage, { ...options, signal });
63468
- const pages = new PagedStorage22({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
64563
+ const pages = new PagedStorage25({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63469
64564
  const base = pages.allocate(0);
63470
64565
  let count = 0, document2;
63471
64566
  let closing;
@@ -63514,6 +64609,14 @@ async function editRetainedDocument(source, storage, options = {}) {
63514
64609
  ...options.maxRecursionDepth === void 0 ? {} : { maxRecursionDepth: options.maxRecursionDepth }
63515
64610
  };
63516
64611
  document2 = await PdfRetainedDocument.openStore(store, storage, { ...configured, ...infoRef ? { infoRef } : {} });
64612
+ if (options.infoUpdates) {
64613
+ const updated = await applyRetainedInfoUpdates(document2, store, storage, count, getPage, options.infoUpdates, signal, options.maxRecursionDepth);
64614
+ infoRef = updated.infoRef;
64615
+ if (updated.idArray) configured.idArray = updated.idArray;
64616
+ await document2.close();
64617
+ document2 = await PdfRetainedDocument.openStore(store, storage, { ...configured, ...infoRef ? { infoRef } : {} });
64618
+ addedObjects = true;
64619
+ }
63517
64620
  for await (const edit of options.rotations ?? []) {
63518
64621
  signal.throwIfAborted();
63519
64622
  if (!Number.isSafeInteger(edit.pageIndex) || edit.pageIndex < 0 || edit.pageIndex >= count) throw new RangeError("Page index out of bounds");
@@ -63572,13 +64675,21 @@ async function editRetainedDocument(source, storage, options = {}) {
63572
64675
  }
63573
64676
  }
63574
64677
  } else if (options.removePageLabels) await removeRoot(["PageLabels"]);
64678
+ if (options.bookmarks) {
64679
+ await setRetainedBookmarks(store, storage, source.crossReference.rootRef, count, reference, options.bookmarks, signal, options.maxRecursionDepth);
64680
+ addedObjects = true;
64681
+ }
64682
+ for await (const update of options.formUpdates ?? []) {
64683
+ await generateRetainedFormAppearances(document2, store, storage, signal, update);
64684
+ addedObjects = true;
64685
+ }
63575
64686
  if (options.generateAppearances && !options.removeAcroform) {
63576
64687
  await generateRetainedFormAppearances(document2, store, storage, signal);
63577
64688
  addedObjects = true;
63578
64689
  }
63579
64690
  if (options.removeInfo) {
63580
64691
  await removeRoot(["Metadata"]);
63581
- const found = await document2.lookup(source.crossReference.infoRef);
64692
+ const found = await document2.lookup(infoRef);
63582
64693
  if (found?.value.kind === "dict" && !found.stream && found.reference) {
63583
64694
  const date = dictGet(found.value, "ModDate");
63584
64695
  found.value.entries.length = 0;
@@ -63617,6 +64728,15 @@ async function editRetainedDocument(source, storage, options = {}) {
63617
64728
  await editRetainedAttachments(document2, store, storage, options.removeAttachments ?? [], options.attachments ?? [], signal);
63618
64729
  addedObjects = true;
63619
64730
  }
64731
+ if (options.appendAttachments) {
64732
+ if (options.attachmentPageIndex !== void 0 && (!Number.isSafeInteger(options.attachmentPageIndex) || options.attachmentPageIndex < 0 || options.attachmentPageIndex >= count)) throw new RangeError("Attachment page index out of bounds");
64733
+ if (addedObjects) {
64734
+ await document2.close();
64735
+ document2 = await PdfRetainedDocument.openStore(store, storage, { ...configured, ...infoRef ? { infoRef } : {} });
64736
+ }
64737
+ await appendRetainedAttachments(document2, store, storage, options.appendAttachments, { signal, ...options.attachmentPageIndex !== void 0 ? { pageIndex: options.attachmentPageIndex } : {} });
64738
+ addedObjects = true;
64739
+ }
63620
64740
  if (addedObjects || infoRef !== source.crossReference.infoRef) {
63621
64741
  await document2.close();
63622
64742
  document2 = await PdfRetainedDocument.openStore(store, storage, { ...configured, ...infoRef ? { infoRef } : {} });
@@ -63674,9 +64794,9 @@ async function* copyRetainedAttachments(document2, storage, options = {}) {
63674
64794
  }
63675
64795
 
63676
64796
  // packages/pdf-ast/src/cos/retained-object-order.ts
63677
- import { IntegerTable as IntegerTable14, PagedStorage as PagedStorage23 } from "@poe-platform/safe-fs/storage";
64797
+ import { IntegerTable as IntegerTable14, PagedStorage as PagedStorage26 } from "@poe-platform/safe-fs/storage";
63678
64798
  async function* retainedObjectOrder(document2, source, storage, signal) {
63679
- const backing = new PagedStorage23({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
64799
+ const backing = new PagedStorage26({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63680
64800
  const seen = new IntegerTable14(backing), streams = new IntegerTable14(backing);
63681
64801
  let failed = false, work = 0;
63682
64802
  async function candidate(number) {
@@ -63813,12 +64933,12 @@ async function* encryptRetainedPdfChunks(source, storage, options = {}) {
63813
64933
  }
63814
64934
 
63815
64935
  // packages/pdf-ast/src/cos/qpdf-json-values.ts
63816
- import { IntegerTable as IntegerTable15, PagedStorage as PagedStorage24 } from "@poe-platform/safe-fs/storage";
64936
+ import { IntegerTable as IntegerTable15, PagedStorage as PagedStorage27 } from "@poe-platform/safe-fs/storage";
63817
64937
  var QpdfJsonValues = class _QpdfJsonValues {
63818
64938
  constructor(tree, storage, signal) {
63819
64939
  this.tree = tree;
63820
64940
  this.signal = signal;
63821
- this.scratch = new PagedStorage24({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
64941
+ this.scratch = new PagedStorage27({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63822
64942
  this.first = new IntegerTable15(this.scratch, 64);
63823
64943
  this.next = new IntegerTable15(this.scratch, 64);
63824
64944
  }
@@ -64211,13 +65331,13 @@ var QpdfJsonValues = class _QpdfJsonValues {
64211
65331
  };
64212
65332
 
64213
65333
  // packages/pdf-ast/src/cos/qpdf-json-document.ts
64214
- import { IntegerTable as IntegerTable16, PagedStorage as PagedStorage25 } from "@poe-platform/safe-fs/storage";
65334
+ import { IntegerTable as IntegerTable16, PagedStorage as PagedStorage28 } from "@poe-platform/safe-fs/storage";
64215
65335
  var QpdfJsonDocument = class _QpdfJsonDocument {
64216
65336
  constructor(storage, options = {}) {
64217
65337
  this.storage = storage;
64218
65338
  this.signal = options.signal ? AbortSignal.any([options.signal, this.controller.signal]) : this.controller.signal;
64219
65339
  this.store = new PdfMutableObjectStore(storage, { signal: this.signal });
64220
- this.backing = new PagedStorage25(
65340
+ this.backing = new PagedStorage28(
64221
65341
  { fs: storage.fs, cwd: storage.directory, env: {}, signal: this.signal },
64222
65342
  4
64223
65343
  );
@@ -64286,7 +65406,7 @@ var QpdfJsonDocument = class _QpdfJsonDocument {
64286
65406
  env: {},
64287
65407
  signal: this.signal
64288
65408
  };
64289
- const tape = new PagedStorage25(context, 4), scratch = new PagedStorage25(context, 4);
65409
+ const tape = new PagedStorage28(context, 4), scratch = new PagedStorage28(context, 4);
64290
65410
  let values, failed = false, work = 0;
64291
65411
  const cooperate = async (units = 1) => {
64292
65412
  this.signal.throwIfAborted();
@@ -64703,6 +65823,8 @@ export {
64703
65823
  rc4Transform,
64704
65824
  readCMapCharacters,
64705
65825
  readCosXrefRevision,
65826
+ readPdfDictionaryEntries,
65827
+ readPdfDictionaryValue,
64706
65828
  readStoredItems,
64707
65829
  redactPageContentAst,
64708
65830
  renderDisplayListToBitmap,