@poe-platform/safe-bash 0.1.812 → 0.1.813

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 (329) 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/office-xml/retained-xml-document.d.ts +8 -0
  10. package/dist/pdf-ast/ast.d.ts +2 -0
  11. package/dist/pdf-ast/content/dictionary-cursor.d.ts +15 -0
  12. package/dist/pdf-ast/content/range-operator-parser.d.ts +4 -0
  13. package/dist/pdf-ast/content/stored-dictionary.d.ts +10 -0
  14. package/dist/pdf-ast/cos/lexer.d.ts +8 -5
  15. package/dist/pdf-ast/cos/object-reader.d.ts +4 -3
  16. package/dist/pdf-ast/cos/range-parser.d.ts +4 -0
  17. package/dist/pdf-ast/cos/retained-objects.d.ts +1 -0
  18. package/dist/pdf-ast/cos/retained-writer.d.ts +1 -0
  19. package/dist/pdf-ast/cos/value-parser.d.ts +9 -0
  20. package/dist/pdf-ast/edit/retained-append-attachments.d.ts +13 -0
  21. package/dist/pdf-ast/edit/retained-bookmarks.d.ts +13 -0
  22. package/dist/pdf-ast/edit/retained-graph.d.ts +6 -0
  23. package/dist/pdf-ast/edit/retained-save.d.ts +2 -0
  24. package/dist/pdf-ast/edit/retained-stamps.d.ts +9 -0
  25. package/dist/pdf-ast/fonts/resolve.d.ts +3 -1
  26. package/dist/pdf-ast/index.d.ts +3 -1
  27. package/dist/pdf-ast/index.js +1557 -770
  28. package/dist/safe-bash/audio-ast.browser.js +6 -1
  29. package/dist/safe-bash/chunks/{chunk-HHSOUC3Z.js → chunk-HPQE675Q.js} +1 -1
  30. package/dist/safe-bash/chunks/{chunk-BUYRKFW2.js → chunk-I6ECNJMR.js} +1 -1
  31. package/dist/safe-bash/chunks/{pdftk-WRYEP3CA.js → pdftk-Y2TX74LY.js} +2 -1
  32. package/dist/safe-bash/command-chunks/biff-4ALVARRF-7SRX6R6N.js +5192 -0
  33. package/dist/safe-bash/command-chunks/{chunk-EHSM5ZQS.js → chunk-2DGJOOXM.js} +8 -8
  34. package/dist/safe-bash/command-chunks/{chunk-Q6S57NOQ.js → chunk-2E2H7MBH.js} +7 -7
  35. package/dist/safe-bash/command-chunks/{chunk-MMBZTYXO.js → chunk-2PQRZDNR.js} +221 -0
  36. package/dist/safe-bash/command-chunks/{chunk-NARD63DY.js → chunk-2V6FOLXV.js} +22 -66
  37. package/dist/safe-bash/command-chunks/{chunk-56NYSX65.js → chunk-2Z3WRRFT.js} +9 -9
  38. package/dist/safe-bash/command-chunks/chunk-3D24WDND.js +63 -0
  39. package/dist/safe-bash/command-chunks/{chunk-47NEG4UO.js → chunk-3JST2Q7G.js} +219 -43
  40. package/dist/safe-bash/command-chunks/{chunk-WGG6G2KG.js → chunk-3LJAXFH5.js} +7 -7
  41. package/dist/safe-bash/command-chunks/{chunk-AHA6IWAJ.js → chunk-3TYDSGAH.js} +6 -6
  42. package/dist/safe-bash/command-chunks/{chunk-YSMNXMAO.js → chunk-3Y4XZB24.js} +4 -4
  43. package/dist/safe-bash/command-chunks/{chunk-ZIIO6GRY.js → chunk-4PBNMKAT.js} +7 -7
  44. package/dist/safe-bash/command-chunks/{chunk-JFYWVQ4V.js → chunk-4Z6W5EOC.js} +8 -8
  45. package/dist/safe-bash/command-chunks/{chunk-GEM47B2P.js → chunk-57DDYKE5.js} +7 -7
  46. package/dist/safe-bash/command-chunks/{chunk-4CKFNXRN.js → chunk-5IFRAI7Y.js} +1 -1
  47. package/dist/safe-bash/command-chunks/{chunk-RHYJVTJO.js → chunk-5KGEZ3RW.js} +2 -2
  48. package/dist/safe-bash/command-chunks/{chunk-A5FZBR7X.js → chunk-5MFDRSGG.js} +4 -4
  49. package/dist/safe-bash/command-chunks/{chunk-7GKKMNL6.js → chunk-5P6I2T63.js} +8 -8
  50. package/dist/safe-bash/command-chunks/{chunk-6M6TM5Z5.js → chunk-5VQVZPP3.js} +3 -3
  51. package/dist/safe-bash/command-chunks/{chunk-MIRL7HTF.js → chunk-6244HYJY.js} +1 -1
  52. package/dist/safe-bash/command-chunks/chunk-63EMPQ7Z.js +115 -0
  53. package/dist/safe-bash/command-chunks/{chunk-XRVKWGVQ.js → chunk-6CY5BHBS.js} +6 -6
  54. package/dist/safe-bash/command-chunks/{chunk-XVP6V5K3.js → chunk-6IWE7PTK.js} +6 -6
  55. package/dist/safe-bash/command-chunks/{chunk-6QBMND4A.js → chunk-6SRHWVEB.js} +1 -1
  56. package/dist/safe-bash/command-chunks/chunk-6ZHQB453.js +35 -0
  57. package/dist/safe-bash/command-chunks/chunk-73NYFNAS.js +173 -0
  58. package/dist/safe-bash/command-chunks/{chunk-2JSDKQ4J.js → chunk-7NXTEWPR.js} +119 -44
  59. package/dist/safe-bash/command-chunks/{chunk-554Z6IKP.js → chunk-7PRL6RJ6.js} +2 -2
  60. package/dist/safe-bash/command-chunks/{chunk-SDTPO2VV.js → chunk-7PZHWMK6.js} +7 -7
  61. package/dist/safe-bash/command-chunks/{chunk-XZ2FWFNV.js → chunk-7QZ2HP2F.js} +6 -6
  62. package/dist/safe-bash/command-chunks/{chunk-OEJM666F.js → chunk-7UC2Q6Z6.js} +5 -5
  63. package/dist/safe-bash/command-chunks/{chunk-COKYZUBW.js → chunk-AJI55RS7.js} +1 -1
  64. package/dist/safe-bash/command-chunks/{chunk-WXRYDALR.js → chunk-BBAB7LC4.js} +4 -4
  65. package/dist/safe-bash/command-chunks/{chunk-QYMEASQ6.js → chunk-BEHUSUOY.js} +4 -4
  66. package/dist/safe-bash/command-chunks/{chunk-Z2JW6M2D.js → chunk-BK7ISUJL.js} +3 -3
  67. package/dist/safe-bash/command-chunks/{chunk-33YCKZZX.js → chunk-C5KLFZGT.js} +6 -6
  68. package/dist/safe-bash/command-chunks/{chunk-TVH4JORU.js → chunk-C5QDEB3I.js} +3 -3
  69. package/dist/safe-bash/command-chunks/{chunk-N4R2SHSS.js → chunk-CCZZVCHX.js} +2 -2
  70. package/dist/safe-bash/command-chunks/{chunk-2VLAXKTS.js → chunk-CTDC4LJT.js} +121 -85
  71. package/dist/safe-bash/command-chunks/{chunk-S6R3IB36.js → chunk-D55REQA3.js} +1 -1
  72. package/dist/safe-bash/command-chunks/{chunk-Y4EYCZFT.js → chunk-D6WJY6QO.js} +10 -10
  73. package/dist/safe-bash/command-chunks/{chunk-2CORNDGF.js → chunk-DBLHCJJU.js} +2 -2
  74. package/dist/safe-bash/command-chunks/{chunk-SPW4GW4Z.js → chunk-DFI7QF3M.js} +2 -2
  75. package/dist/safe-bash/command-chunks/{chunk-456PHA3L.js → chunk-DMCI6T6N.js} +1 -1
  76. package/dist/safe-bash/command-chunks/{chunk-TW73OXPR.js → chunk-EJTNVXWF.js} +6 -6
  77. package/dist/safe-bash/command-chunks/{chunk-QD7ZRDUN.js → chunk-ET2VPDUA.js} +1 -1
  78. package/dist/safe-bash/command-chunks/{chunk-CJQSAATC.js → chunk-EXOQGXEU.js} +26 -26
  79. package/dist/safe-bash/command-chunks/{chunk-CRV2Q3PB.js → chunk-EZ4NQIPL.js} +1 -1
  80. package/dist/safe-bash/command-chunks/chunk-FWKLBDMK.js +0 -0
  81. package/dist/safe-bash/command-chunks/{chunk-22MOB45U.js → chunk-FWPVQGYK.js} +6 -6
  82. package/dist/safe-bash/command-chunks/{chunk-QC5RMGSA.js → chunk-G3RUXKVY.js} +3 -3
  83. package/dist/safe-bash/command-chunks/{chunk-JYUJAF4L.js → chunk-G7NENPYV.js} +4 -0
  84. package/dist/safe-bash/command-chunks/{chunk-KCOJA7EM.js → chunk-GKILM4HZ.js} +7 -7
  85. package/dist/safe-bash/command-chunks/{chunk-HTVIYLVB.js → chunk-GNXTMSYN.js} +4 -4
  86. package/dist/safe-bash/command-chunks/{chunk-D2ASPM7R.js → chunk-GOBUDKZ3.js} +3 -3
  87. package/dist/safe-bash/command-chunks/{chunk-RNSKXOG3.js → chunk-GVWVRPG6.js} +6 -6
  88. package/dist/safe-bash/command-chunks/{chunk-FDCIPJBQ.js → chunk-HCKYUQ3L.js} +7 -7
  89. package/dist/safe-bash/command-chunks/{chunk-AGLK7OJR.js → chunk-HDSIIQBS.js} +1 -1
  90. package/dist/safe-bash/command-chunks/{chunk-DM2CPMB4.js → chunk-HKOMXGJS.js} +2 -2
  91. package/dist/safe-bash/command-chunks/{chunk-IT7TAC3F.js → chunk-HVW53ARH.js} +16 -16
  92. package/dist/safe-bash/command-chunks/{chunk-M7QE2MN7.js → chunk-I4GMCWAT.js} +6 -6
  93. package/dist/safe-bash/command-chunks/{chunk-HWQ2UHMT.js → chunk-IHSOOSNC.js} +9 -9
  94. package/dist/safe-bash/command-chunks/{chunk-LCZDBW55.js → chunk-JAHJWVGF.js} +5 -5
  95. package/dist/safe-bash/command-chunks/{chunk-MOZD7RUY.js → chunk-JORIVUPM.js} +27 -11
  96. package/dist/safe-bash/command-chunks/{chunk-PMAM4N33.js → chunk-JUJHYPYL.js} +9 -9
  97. package/dist/safe-bash/command-chunks/{chunk-ENT3IV2G.js → chunk-KBUBSMCQ.js} +12 -12
  98. package/dist/safe-bash/command-chunks/{chunk-ZXR6LXV5.js → chunk-KCE5D4Z4.js} +48 -4
  99. package/dist/safe-bash/command-chunks/{chunk-FIIAYCWS.js → chunk-KZ5ODST6.js} +2 -2
  100. package/dist/safe-bash/command-chunks/{chunk-PNGDJA6M.js → chunk-LD7BONZY.js} +2 -2
  101. package/dist/safe-bash/command-chunks/{chunk-KJ4XXZIL.js → chunk-M3Z5PU2M.js} +582 -59
  102. package/dist/safe-bash/command-chunks/{chunk-LXLLA4PM.js → chunk-MKX4JAZ6.js} +17 -17
  103. package/dist/safe-bash/command-chunks/{chunk-RQIQ75W5.js → chunk-MNHBQBF6.js} +5 -5
  104. package/dist/safe-bash/command-chunks/{chunk-A2CLZMQZ.js → chunk-MPKY37QR.js} +1 -1
  105. package/dist/safe-bash/command-chunks/{chunk-K5GB2YMN.js → chunk-MUUWBZIC.js} +10 -10
  106. package/dist/safe-bash/command-chunks/{chunk-JOCFI7TG.js → chunk-N32GSM3J.js} +1 -1
  107. package/dist/safe-bash/command-chunks/{chunk-EUT24Y5Z.js → chunk-NKTULXVD.js} +8 -8
  108. package/dist/safe-bash/command-chunks/{chunk-5HPU7D36.js → chunk-NMPED6L5.js} +4 -4
  109. package/dist/safe-bash/command-chunks/{chunk-QZZ73J2O.js → chunk-NPFHUS4X.js} +6 -6
  110. package/dist/safe-bash/command-chunks/{chunk-X7FA7ZD5.js → chunk-O675URF4.js} +8 -8
  111. package/dist/safe-bash/command-chunks/{chunk-R6EGGK5M.js → chunk-P7EL2FWW.js} +7 -7
  112. package/dist/safe-bash/command-chunks/{chunk-YS25EI54.js → chunk-PCCFLPUQ.js} +2 -2
  113. package/dist/safe-bash/command-chunks/{chunk-RRL3Y562.js → chunk-PI6MOMHA.js} +11 -11
  114. package/dist/safe-bash/command-chunks/{chunk-26VCZHLJ.js → chunk-PIOQBOEK.js} +1 -1
  115. package/dist/safe-bash/command-chunks/chunk-PK36TVXB.js +175 -0
  116. package/dist/safe-bash/command-chunks/{chunk-3Q247UDJ.js → chunk-PKLJRB7W.js} +264 -129
  117. package/dist/safe-bash/command-chunks/{chunk-6CCQI6XZ.js → chunk-PSCOXGCA.js} +12 -12
  118. package/dist/safe-bash/command-chunks/{chunk-XPD636C4.js → chunk-PVGZMLC6.js} +3 -3
  119. package/dist/safe-bash/command-chunks/{chunk-JQVHUSDD.js → chunk-PXWS3Q7L.js} +5 -5
  120. package/dist/safe-bash/command-chunks/{chunk-HDJVJTCK.js → chunk-QFF5KBOM.js} +9 -9
  121. package/dist/safe-bash/command-chunks/{chunk-MPUHH2KR.js → chunk-QM2HZJSJ.js} +3 -3
  122. package/dist/safe-bash/command-chunks/{chunk-UAXSE3XE.js → chunk-R2BMZAHG.js} +5 -5
  123. package/dist/safe-bash/command-chunks/{chunk-KB7DUBVL.js → chunk-RGOQKIG6.js} +5 -5
  124. package/dist/safe-bash/command-chunks/{chunk-D2KZ66W4.js → chunk-RLCQ7BN3.js} +187 -39
  125. package/dist/safe-bash/command-chunks/{chunk-B5LDP7AA.js → chunk-S2N2V5U4.js} +2 -2
  126. package/dist/safe-bash/command-chunks/{chunk-OA75SGN2.js → chunk-SGPCXAG7.js} +7 -7
  127. package/dist/safe-bash/command-chunks/{chunk-QUM3SYAJ.js → chunk-SYSX46IV.js} +3 -3
  128. package/dist/safe-bash/command-chunks/chunk-T3E5RV3U.js +737 -0
  129. package/dist/safe-bash/command-chunks/{chunk-YORJDX4V.js → chunk-T5ERNELL.js} +4 -4
  130. package/dist/safe-bash/command-chunks/{chunk-ZEX53S5I.js → chunk-T6C5QP7T.js} +6368 -6230
  131. package/dist/safe-bash/command-chunks/{chunk-ATTWQVR2.js → chunk-TKRLZIFI.js} +17 -17
  132. package/dist/safe-bash/command-chunks/{chunk-ZMHEGDU2.js → chunk-TODWFDYB.js} +2 -2
  133. package/dist/safe-bash/command-chunks/{chunk-XVLWZTPY.js → chunk-TQEB4DH4.js} +543 -144
  134. package/dist/safe-bash/command-chunks/{chunk-36XGIPOG.js → chunk-U5TWQFZY.js} +1 -1
  135. package/dist/safe-bash/command-chunks/{chunk-APEWTWCC.js → chunk-UAF4IX5H.js} +6 -6
  136. package/dist/safe-bash/command-chunks/{chunk-6VPQ3CDZ.js → chunk-V37D6AHO.js} +5 -5
  137. package/dist/safe-bash/command-chunks/{chunk-RID6VYS3.js → chunk-V6XBEYPC.js} +8 -8
  138. package/dist/safe-bash/command-chunks/{chunk-WJCN2IXI.js → chunk-VQOINPVF.js} +2 -2
  139. package/dist/safe-bash/command-chunks/{chunk-W5YSINXC.js → chunk-VVWXY6IA.js} +6 -6
  140. package/dist/safe-bash/command-chunks/{chunk-HKATEVAP.js → chunk-WPVBUVFK.js} +6 -6
  141. package/dist/safe-bash/command-chunks/{chunk-UYWSIIUX.js → chunk-X53AEG36.js} +7 -7
  142. package/dist/safe-bash/command-chunks/{chunk-L5MCW6CM.js → chunk-X64XGIXZ.js} +9 -155
  143. package/dist/safe-bash/command-chunks/{chunk-Q73EMLLZ.js → chunk-X6RHJ6YN.js} +84 -5
  144. package/dist/safe-bash/command-chunks/{chunk-7PVHO47B.js → chunk-XG6UWQV5.js} +6 -6
  145. package/dist/safe-bash/command-chunks/{chunk-NQDIT667.js → chunk-XIDGHIGB.js} +5 -5
  146. package/dist/safe-bash/command-chunks/{chunk-CV7M2QJU.js → chunk-XLYIVBAR.js} +7 -7
  147. package/dist/safe-bash/command-chunks/{chunk-WVMHRNXZ.js → chunk-YUXTK3XA.js} +3 -3
  148. package/dist/safe-bash/command-chunks/{chunk-SPLOIABU.js → chunk-YXD6VGVG.js} +3 -3
  149. package/dist/safe-bash/command-chunks/{chunk-2ZFLMWOX.js → chunk-Z5BIM5B7.js} +1 -1
  150. package/dist/safe-bash/command-chunks/chunk-ZYLGNIGA.js +156 -0
  151. package/dist/safe-bash/command-chunks/{command-engine-BCUQGJJ4.js → command-engine-X3OLN7N6.js} +150 -67
  152. package/dist/safe-bash/command-chunks/{engine-LAUEWYSQ-DQCEI5HE.js → engine-XUCIFZ7V-LJFGZM6O.js} +1 -1
  153. package/dist/safe-bash/command-chunks/paradox-4FCZE53D-LQPGVMEL.js +365 -0
  154. package/dist/safe-bash/commands/pandoc/index.browser.js +1 -1
  155. package/dist/safe-bash/full-core.browser.js +2 -2
  156. package/dist/safe-bash/plugins/index.browser.js +2 -2
  157. package/dist/safe-bash-command-diff/diff.js +1 -1
  158. package/dist/safe-bash-command-diff/index.js +1 -1
  159. package/dist/safe-bash-command-ffmpeg/index.js +1 -1
  160. package/dist/safe-bash-command-ffprobe/index.js +2 -2
  161. package/dist/safe-bash-command-ffprobe/media.d.ts +3 -1
  162. package/dist/safe-bash-command-ffprobe/media.js +2 -2
  163. package/dist/safe-bash-command-html-to-markdown/budget.js +2 -1
  164. package/dist/safe-bash-command-html-to-markdown/entities.js +4 -3
  165. package/dist/safe-bash-command-html-to-markdown/index.js +564 -110
  166. package/dist/safe-bash-command-html-to-markdown/input.js +6 -5
  167. package/dist/safe-bash-command-html-to-markdown/options.js +2 -1
  168. package/dist/safe-bash-command-html-to-markdown/parser.js +5 -4
  169. package/dist/safe-bash-command-html-to-markdown/render.js +6 -5
  170. package/dist/safe-bash-command-html-to-markdown/text.js +3 -2
  171. package/dist/safe-bash-command-htmlq/index.js +361 -37
  172. package/dist/safe-bash-command-htmlq/tree.d.ts +3 -2
  173. package/dist/safe-bash-command-pandoc/command.js +7 -7
  174. package/dist/safe-bash-command-pandoc/index.js +55 -55
  175. package/dist/safe-bash-command-patch/index.js +6 -6
  176. package/dist/safe-bash-command-patch/patch-envelope.js +53 -3
  177. package/dist/safe-bash-command-patch/patch-formats.d.ts +2 -2
  178. package/dist/safe-bash-command-patch/patch-formats.js +2 -2
  179. package/dist/safe-bash-command-patch/patch-gnu-reject.d.ts +2 -1
  180. package/dist/safe-bash-command-patch/patch-gnu-reject.js +4 -3
  181. package/dist/safe-bash-command-patch/patch-publication.js +2 -1
  182. package/dist/safe-bash-command-patch/patch.js +6 -6
  183. package/dist/safe-bash-command-patch/unified.d.ts +10 -2
  184. package/dist/safe-bash-command-patch/unified.js +1 -1
  185. package/dist/safe-bash-command-pdftk/index.d.ts +6 -2
  186. package/dist/safe-bash-command-pdftk/index.js +830 -271
  187. package/dist/safe-bash-command-pptx/command-engine.d.ts +3 -0
  188. package/dist/safe-bash-command-pptx/engine.js +1 -1
  189. package/dist/safe-bash-command-pptx/index.js +9 -2
  190. package/dist/safe-bash-command-soffice/index.js +1 -1
  191. package/dist/safe-bash-command-ssconvert/index.js +2 -2
  192. package/dist/safe-bash-command-xmllint/index.js +22 -31
  193. package/dist/safe-bash-presentation-engine/accessibility.js +31 -30
  194. package/dist/safe-bash-presentation-engine/animation-editing.js +16 -15
  195. package/dist/safe-bash-presentation-engine/animations.js +16 -15
  196. package/dist/safe-bash-presentation-engine/backgrounds.js +17 -16
  197. package/dist/safe-bash-presentation-engine/bytes.js +3 -3
  198. package/dist/safe-bash-presentation-engine/chart-editing.js +34 -33
  199. package/dist/safe-bash-presentation-engine/chart-object-operations.js +25 -24
  200. package/dist/safe-bash-presentation-engine/charts.js +31 -30
  201. package/dist/safe-bash-presentation-engine/command-placeholder.js +59 -56
  202. package/dist/safe-bash-presentation-engine/comments.js +17 -16
  203. package/dist/safe-bash-presentation-engine/connector-operations.js +32 -31
  204. package/dist/safe-bash-presentation-engine/connectors.js +29 -28
  205. package/dist/safe-bash-presentation-engine/content-types.js +4 -4
  206. package/dist/safe-bash-presentation-engine/creation.js +6 -6
  207. package/dist/safe-bash-presentation-engine/diff.js +32 -31
  208. package/dist/safe-bash-presentation-engine/drawing-enums.d.ts +10 -10
  209. package/dist/safe-bash-presentation-engine/drawing-format.js +20 -19
  210. package/dist/safe-bash-presentation-engine/drawing-operations.js +31 -30
  211. package/dist/safe-bash-presentation-engine/drawing-schema.js +21 -20
  212. package/dist/safe-bash-presentation-engine/equations.js +17 -16
  213. package/dist/safe-bash-presentation-engine/errors.js +2 -2
  214. package/dist/safe-bash-presentation-engine/fields.js +17 -16
  215. package/dist/safe-bash-presentation-engine/font-metrics.js +3 -3
  216. package/dist/safe-bash-presentation-engine/image-extraction.js +20 -19
  217. package/dist/safe-bash-presentation-engine/image-formatting.js +32 -31
  218. package/dist/safe-bash-presentation-engine/image-insertion.js +18 -17
  219. package/dist/safe-bash-presentation-engine/image-replacement.js +21 -20
  220. package/dist/safe-bash-presentation-engine/image-value.js +4 -4
  221. package/dist/safe-bash-presentation-engine/images.js +19 -18
  222. package/dist/safe-bash-presentation-engine/index.d.ts +5 -1
  223. package/dist/safe-bash-presentation-engine/index.js +109 -96
  224. package/dist/safe-bash-presentation-engine/layouts.js +16 -15
  225. package/dist/safe-bash-presentation-engine/length.js +3 -3
  226. package/dist/safe-bash-presentation-engine/links.js +16 -15
  227. package/dist/safe-bash-presentation-engine/masters.js +15 -14
  228. package/dist/safe-bash-presentation-engine/media-editing.js +24 -23
  229. package/dist/safe-bash-presentation-engine/media-extraction.js +17 -16
  230. package/dist/safe-bash-presentation-engine/media.js +16 -15
  231. package/dist/safe-bash-presentation-engine/memberships.js +15 -14
  232. package/dist/safe-bash-presentation-engine/notes.js +16 -15
  233. package/dist/safe-bash-presentation-engine/ole-enum.js +4 -4
  234. package/dist/safe-bash-presentation-engine/ole-insertion.js +20 -19
  235. package/dist/safe-bash-presentation-engine/opaque-objects.js +9 -9
  236. package/dist/safe-bash-presentation-engine/package-reader.js +5 -5
  237. package/dist/safe-bash-presentation-engine/package-tools.d.ts +3 -0
  238. package/dist/safe-bash-presentation-engine/package-tools.js +27 -17
  239. package/dist/safe-bash-presentation-engine/package-uri.js +3 -3
  240. package/dist/safe-bash-presentation-engine/package-writer.js +4 -4
  241. package/dist/safe-bash-presentation-engine/presentation-model.js +58 -55
  242. package/dist/safe-bash-presentation-engine/presentation-settings.js +14 -13
  243. package/dist/safe-bash-presentation-engine/properties.js +16 -15
  244. package/dist/safe-bash-presentation-engine/relationships.js +4 -4
  245. package/dist/safe-bash-presentation-engine/resource-limits.js +1 -1
  246. package/dist/safe-bash-presentation-engine/retained-archive-staging.d.ts +19 -0
  247. package/dist/safe-bash-presentation-engine/retained-extraction-output.d.ts +18 -0
  248. package/dist/safe-bash-presentation-engine/retained-inspection.js +14 -12
  249. package/dist/safe-bash-presentation-engine/retained-package-extraction.d.ts +22 -0
  250. package/dist/safe-bash-presentation-engine/retained-package-packing.d.ts +19 -0
  251. package/dist/safe-bash-presentation-engine/retained-package.d.ts +2 -0
  252. package/dist/safe-bash-presentation-engine/retained-package.js +6 -4
  253. package/dist/safe-bash-presentation-engine/retained-text.js +19 -17
  254. package/dist/safe-bash-presentation-engine/retained-xml-parts.d.ts +5 -1
  255. package/dist/safe-bash-presentation-engine/retained-xml-publication.d.ts +18 -0
  256. package/dist/safe-bash-presentation-engine/retained-xml-replacement.d.ts +13 -0
  257. package/dist/safe-bash-presentation-engine/sanitize.js +17 -16
  258. package/dist/safe-bash-presentation-engine/selectors.js +10 -10
  259. package/dist/safe-bash-presentation-engine/shape-groups.js +31 -30
  260. package/dist/safe-bash-presentation-engine/shape-operations.js +30 -29
  261. package/dist/safe-bash-presentation-engine/shape-path-operations.js +32 -31
  262. package/dist/safe-bash-presentation-engine/shape-paths.js +16 -15
  263. package/dist/safe-bash-presentation-engine/shape-presets.js +3 -3
  264. package/dist/safe-bash-presentation-engine/shape-selection.js +31 -30
  265. package/dist/safe-bash-presentation-engine/shape-transforms.js +18 -17
  266. package/dist/safe-bash-presentation-engine/shapes.d.ts +1 -1
  267. package/dist/safe-bash-presentation-engine/shapes.js +27 -26
  268. package/dist/safe-bash-presentation-engine/slide-copy.js +17 -16
  269. package/dist/safe-bash-presentation-engine/slide-import.js +18 -17
  270. package/dist/safe-bash-presentation-engine/slide-merge-split.js +20 -19
  271. package/dist/safe-bash-presentation-engine/slide-model.js +43 -42
  272. package/dist/safe-bash-presentation-engine/slide-removal.js +18 -17
  273. package/dist/safe-bash-presentation-engine/slide-transfer-budget.js +9 -9
  274. package/dist/safe-bash-presentation-engine/slides.js +19 -16
  275. package/dist/safe-bash-presentation-engine/table-operations.js +33 -32
  276. package/dist/safe-bash-presentation-engine/table-spans.js +32 -31
  277. package/dist/safe-bash-presentation-engine/tables.js +31 -30
  278. package/dist/safe-bash-presentation-engine/tags.js +16 -15
  279. package/dist/safe-bash-presentation-engine/template-bindings.js +33 -32
  280. package/dist/safe-bash-presentation-engine/template-repeat.js +40 -39
  281. package/dist/safe-bash-presentation-engine/text-fitting.js +27 -26
  282. package/dist/safe-bash-presentation-engine/text-frames.js +27 -26
  283. package/dist/safe-bash-presentation-engine/text-paragraphs.js +27 -26
  284. package/dist/safe-bash-presentation-engine/text-reading.js +11 -11
  285. package/dist/safe-bash-presentation-engine/text-replacement.js +17 -16
  286. package/dist/safe-bash-presentation-engine/text-runs.js +20 -19
  287. package/dist/safe-bash-presentation-engine/themes.js +16 -15
  288. package/dist/safe-bash-presentation-engine/transitions.js +16 -15
  289. package/dist/safe-bash-presentation-engine/validation.js +10 -9
  290. package/dist/safe-bash-presentation-engine/xml-parts.d.ts +2 -0
  291. package/dist/safe-bash-presentation-engine/xml-parts.js +23 -15
  292. package/dist/safe-bash-presentation-engine/xml-view.js +3 -3
  293. package/dist/safe-bash-presentation-engine/xml.js +3 -3
  294. package/dist/safe-bash-regex-engine/index.js +1 -1
  295. package/dist/safe-bash-regex-engine/python-glob.js +1 -1
  296. package/dist/safe-bash-regex-engine/text/regex.d.ts +19 -0
  297. package/dist/safe-bash-regex-engine/text/regex.js +1 -1
  298. package/dist/safe-bash-xml-engine/document.js +3 -3
  299. package/dist/safe-bash-xml-engine/evaluate.js +1 -1
  300. package/dist/safe-bash-xml-engine/index.d.ts +1 -0
  301. package/dist/safe-bash-xml-engine/index.js +8 -4
  302. package/dist/safe-bash-xml-engine/query.js +2 -2
  303. package/dist/safe-bash-xml-engine/recovery.d.ts +10 -0
  304. package/dist/safe-bash-xml-engine/stored-document.d.ts +1 -1
  305. package/dist/safe-bash-xml-engine/stored-document.js +1 -1
  306. package/dist/safe-bash-xml-engine/stored-evaluate.js +1 -1
  307. package/dist/spreadsheet-engine/formulas/functions/python-printf.js +56 -33
  308. package/dist/spreadsheet-format-xls/biff-encrypted-properties.d.ts +1 -1
  309. package/dist/spreadsheet-format-xls/biff-encrypted-properties.js +47 -18
  310. package/dist/spreadsheet-format-xls/biff-properties-merge.d.ts +6 -2
  311. package/dist/spreadsheet-format-xls/biff-properties-merge.js +413 -296
  312. package/dist/spreadsheet-format-xls/biff-properties-write.js +40 -23
  313. package/dist/spreadsheet-format-xls/biff-properties.js +3 -68
  314. package/dist/spreadsheet-format-xls/biff-property-index.d.ts +23 -0
  315. package/dist/spreadsheet-format-xls/biff-property-index.js +93 -0
  316. package/dist/spreadsheet-format-xls/biff-property-name.d.ts +4 -0
  317. package/dist/spreadsheet-format-xls/biff-property-name.js +114 -0
  318. package/dist/spreadsheet-format-xls/biff-property-text.d.ts +6 -0
  319. package/dist/spreadsheet-format-xls/biff-property-text.js +68 -0
  320. package/dist/spreadsheet-format-xls/biff-property-transcode.d.ts +5 -0
  321. package/dist/spreadsheet-format-xls/biff-property-transcode.js +45 -0
  322. package/package.json +6 -3
  323. package/dist/safe-bash/command-chunks/biff-YKPDH35C-MVQIWNKV.js +0 -4974
  324. package/dist/safe-bash/command-chunks/chunk-5Q22ZLNC.js +0 -127
  325. package/dist/safe-bash/command-chunks/chunk-JKLOBSMP.js +0 -56
  326. package/dist/safe-bash/command-chunks/chunk-JYTESTBS.js +0 -99
  327. package/dist/safe-bash/command-chunks/chunk-ZEGNRZV2.js +0 -333
  328. package/dist/safe-bash/command-chunks/paradox-ZWWXYY4J-JYOSWSBL.js +0 -362
  329. package/dist/spreadsheet-format-xls/biff-properties-layout.js +0 -56
@@ -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" && 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);
@@ -44064,8 +44631,8 @@ function* preparePageAppearanceSteps(pageDict, pageRes, evalResourcesDict, hideA
44064
44631
  const sub = yield* resolveDict3(entry.value, [entry.key.decoded]);
44065
44632
  if (sub) {
44066
44633
  onAllocation?.(64 + sub.entries.length * 64);
44067
- const clonedSub = cosDict({});
44068
- for (const se of sub.entries) dictSet(clonedSub, se.key.decoded, se.value);
44634
+ const clonedSub = sub.storedEntries ? yield { kind: "dictionary-merge", destination: sub } : cosDict({});
44635
+ if (!sub.storedEntries) for (const se of sub.entries) dictSet(clonedSub, se.key.decoded, se.value);
44069
44636
  dictSet(evalResourcesDict, entry.key.decoded, clonedSub);
44070
44637
  } else {
44071
44638
  dictSet(evalResourcesDict, entry.key.decoded, entry.value);
@@ -44118,6 +44685,11 @@ function* preparePageAppearanceSteps(pageDict, pageRes, evalResourcesDict, hideA
44118
44685
  dstSub = cosDict({});
44119
44686
  dictSet(evalResourcesDict, subKey, dstSub);
44120
44687
  }
44688
+ if (srcSub.storedEntries || dstSub.storedEntries) {
44689
+ const merged = yield { kind: "dictionary-merge", destination: dstSub, source: srcSub };
44690
+ dictSet(evalResourcesDict, subKey, merged);
44691
+ continue;
44692
+ }
44121
44693
  for (const se of srcSub.entries) {
44122
44694
  if (!dictGet(dstSub, se.key.decoded)) {
44123
44695
  onAllocation?.(64);
@@ -45870,7 +46442,7 @@ var PdfPage = class {
45870
46442
  const request = step.value;
45871
46443
  if (request.kind === "resolve" || request.kind === "catalog") {
45872
46444
  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");
46445
+ } else if (request.kind === "dictionary-merge" || request.kind === "array-reference" || request.kind === "array-item") throw new TypeError("Stored visibility requires asynchronous evaluation");
45874
46446
  else if (request.kind === "appearance-content") {
45875
46447
  appearance = parseContentStream(this.cosDoc.decodeStream(request.stream));
45876
46448
  step = work.next(appearance.length > 0);
@@ -48147,7 +48719,7 @@ async function renderRetainedPagePixels(page2, storage, options = {}) {
48147
48719
  }
48148
48720
 
48149
48721
  // packages/pdf-ast/src/cos/range-parser.ts
48150
- import { listenForAbort } from "@poe-platform/safe-fs/contracts";
48722
+ import { listenForAbort as listenForAbort2 } from "@poe-platform/safe-fs/contracts";
48151
48723
  function limit(value, name) {
48152
48724
  const result = value ?? Infinity;
48153
48725
  if (result !== Infinity && (!Number.isSafeInteger(result) || result < 0)) throw new RangeError(`Invalid ${name}`);
@@ -48199,7 +48771,7 @@ async function resolveStreamLength(entry, options) {
48199
48771
  let dispose = () => {
48200
48772
  };
48201
48773
  const cancelled = new Promise((ignored, reject) => {
48202
- dispose = listenForAbort(signal, () => reject(signal.reason));
48774
+ dispose = listenForAbort2(signal, () => reject(signal.reason));
48203
48775
  });
48204
48776
  const pending = Promise.resolve().then(() => {
48205
48777
  signal.throwIfAborted();
@@ -48222,10 +48794,10 @@ async function readValue(lexer, depth, nodes, options) {
48222
48794
  while (!step.done) {
48223
48795
  signal?.throwIfAborted();
48224
48796
  const request = step.value;
48225
- if (request && request !== "token" && request.kind === "array-append") {
48797
+ if (request && request !== "token" && (request.kind === "array-append" || request.kind === "dictionary-append")) {
48226
48798
  let position;
48227
48799
  try {
48228
- position = await appendStoredRecord(options.arrayStorage, request.node, request.previous, signal);
48800
+ position = await appendStoredRecord(request.kind === "array-append" ? options.arrayStorage : options.dictionaryStorage, request.kind === "array-append" ? request.node : request.entry, request.previous, signal);
48229
48801
  } catch (error) {
48230
48802
  options.onBackingError?.(error);
48231
48803
  throw error;
@@ -48255,7 +48827,7 @@ async function parseCosRangeValue(source, offset, options = {}) {
48255
48827
  const depth = limit(options.maxRecursionDepth, "maxRecursionDepth");
48256
48828
  const nodes = limit(options.maxNodes, "maxNodes");
48257
48829
  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 } : {} });
48830
+ 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
48831
  return { value: await readValue(lexer, depth, nodes, options), offset: lexer.offset };
48260
48832
  }
48261
48833
  async function parseCosRangeObject(source, offset, options = {}) {
@@ -48264,7 +48836,7 @@ async function parseCosRangeObject(source, offset, options = {}) {
48264
48836
  const tokenBytes = limit(options.maxTokenBytes, "maxTokenBytes");
48265
48837
  const { signal } = options;
48266
48838
  signal?.throwIfAborted();
48267
- const lexer = new CosRangeLexer(source, { ...options.onBackingError ? { onBackingError: options.onBackingError } : {}, start: offset, maxTokenBytes: tokenBytes, ...signal ? { signal } : {} });
48839
+ 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
48840
  const object = await lexer.nextToken();
48269
48841
  const generation = await lexer.nextToken();
48270
48842
  const keyword = await lexer.nextToken();
@@ -48373,7 +48945,7 @@ async function* scanCosRangeObjects(source, options = {}) {
48373
48945
 
48374
48946
  // packages/pdf-ast/src/cos/range-xref.ts
48375
48947
  import { readBytes as readBytes12 } from "@poe-platform/safe-fs/contracts";
48376
- function budget(value, name) {
48948
+ function budget2(value, name) {
48377
48949
  if (value === void 0 || value === Infinity) return Infinity;
48378
48950
  if (!Number.isSafeInteger(value) || value < 0) throw new RangeError(`Invalid ${name}`);
48379
48951
  return value;
@@ -48432,12 +49004,12 @@ var DecodedFields = class {
48432
49004
  }
48433
49005
  };
48434
49006
  async function* readCosXrefRevision(source, offset, options = {}) {
48435
- const maximum10 = budget(options.maxEntries, "maxEntries");
48436
- const maxDecoded = budget(options.maxDecodedBytes, "maxDecodedBytes");
49007
+ const maximum10 = budget2(options.maxEntries, "maxEntries");
49008
+ const maxDecoded = budget2(options.maxDecodedBytes, "maxDecodedBytes");
48437
49009
  const { signal } = options;
48438
49010
  signal?.throwIfAborted();
48439
49011
  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 } });
49012
+ 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
49013
  const first = await lexer.nextToken();
48442
49014
  let admitted = 0;
48443
49015
  const admit2 = (count) => {
@@ -48552,271 +49124,6 @@ async function* readCosXrefRevision(source, offset, options = {}) {
48552
49124
  }
48553
49125
  }
48554
49126
 
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
49127
  // packages/pdf-ast/src/cos/cross-reference.ts
48821
49128
  var marker = new TextEncoder().encode("startxref");
48822
49129
  async function header(source, signal) {
@@ -48851,6 +49158,8 @@ async function findPdfStartXref(source, options = {}) {
48851
49158
  if (!matched) continue;
48852
49159
  const lexer = new CosRangeLexer(source, {
48853
49160
  start: start + i + marker.length,
49161
+ compactNumbers: options.compactNumbers ?? false,
49162
+ compactKeywords: options.compactKeywords ?? false,
48854
49163
  ...options.maxTokenBytes === void 0 ? {} : { maxTokenBytes: options.maxTokenBytes },
48855
49164
  ...options.signal ? { signal: options.signal } : {}
48856
49165
  });
@@ -48992,8 +49301,23 @@ async function resolvePdfStreamDictionary(dict, lookup, active, options) {
48992
49301
  }
48993
49302
  if (node.kind === "array") {
48994
49303
  const items = [];
48995
- for (const item of node.items) items.push(await resolve2(item, depth + 1));
48996
- return { ...node, items };
49304
+ const { storedItems, ...ordinary } = node;
49305
+ if (storedItems) {
49306
+ const reader = readStoredItems(storedItems, options.signal);
49307
+ try {
49308
+ for (; ; ) {
49309
+ const item = await reader.next().catch((error) => {
49310
+ options.onBackingError?.(error);
49311
+ throw error;
49312
+ });
49313
+ if (item.done) break;
49314
+ items.push(await resolve2(item.value, depth + 1));
49315
+ }
49316
+ } finally {
49317
+ await reader.return();
49318
+ }
49319
+ } else for (const item of node.items) items.push(await resolve2(item, depth + 1));
49320
+ return { ...ordinary, items };
48997
49321
  }
48998
49322
  if (node.kind === "dict") {
48999
49323
  const entries2 = [];
@@ -49216,6 +49540,9 @@ var PdfObjectReader = class {
49216
49540
  index;
49217
49541
  storage;
49218
49542
  streams = /* @__PURE__ */ new Map();
49543
+ // Recursive length/object-stream lookups share one failure identity so an
49544
+ // outer recovery pass cannot mistake a caller-storage error for PDF syntax.
49545
+ backingFailures = /* @__PURE__ */ new WeakMap();
49219
49546
  repairedOffsets = /* @__PURE__ */ new Map();
49220
49547
  options;
49221
49548
  capacity;
@@ -49245,7 +49572,10 @@ var PdfObjectReader = class {
49245
49572
  const object2 = await this.load(objectNumber, generationNumber, /* @__PURE__ */ new Set());
49246
49573
  if (object2?.value.kind !== "dict" || !object2.stream) throw new PdfError("E_PARSE", "Expected an indexed PDF stream");
49247
49574
  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) };
49575
+ return { object: object2, dict: await resolvePdfStreamDictionary(object2.value, (ref) => this.load(ref.objectNumber, ref.generationNumber, active), active, { ...this.options, onBackingError: (error) => {
49576
+ this.backingFailures.set(active, { error });
49577
+ this.options.onBackingError?.(error);
49578
+ } }) };
49249
49579
  });
49250
49580
  const span = object.stream;
49251
49581
  const input = () => this.source.stream(span.start, span.end - span.start, this.options.signal);
@@ -49253,13 +49583,17 @@ var PdfObjectReader = class {
49253
49583
  const decodeOptions = { ...this.options, stopBeforeImageCodec: options.stopBeforeImageCodec ?? false, raw: options.raw ?? false };
49254
49584
  yield* security ? decodePdfEncryptedStreamChunks(security, objectNumber, generationNumber, dict, input, decodeOptions) : decodePdfStreamChunks(dict, input, decodeOptions);
49255
49585
  }
49256
- async load(objectNumber, generationNumber, active, arrays = {}) {
49586
+ async load(objectNumber, generationNumber, active, arrays = this.options.valueArrays ?? {}) {
49257
49587
  this.options.signal?.throwIfAborted();
49258
49588
  if (active.has(objectNumber)) throw new PdfError("E_PARSE", "PDF indirect object cycle");
49259
49589
  if (active.size >= this.options.maxRecursionDepth) throw new PdfError("E_LIMIT", "PDF object resolution depth limit exceeded");
49260
49590
  const entry = await this.index.get(objectNumber, this.options.signal);
49261
49591
  if (!entry || entry.type === "free" || generationNumber !== (entry.generationNumber ?? 0)) return void 0;
49262
49592
  active.add(objectNumber);
49593
+ const onBackingError = (error) => {
49594
+ this.backingFailures.set(active, { error });
49595
+ this.options.onBackingError?.(error);
49596
+ };
49263
49597
  try {
49264
49598
  if (entry.type === "compressed") {
49265
49599
  const container = entry.objectStreamNumber;
@@ -49272,15 +49606,11 @@ var PdfObjectReader = class {
49272
49606
  if (row.number !== objectNumber) throw new PdfError("E_PARSE", "Compressed object identity does not match xref");
49273
49607
  const end = ordinal + 1 === stream.count ? stream.data.size : stream.first + (await this.headerRow(stream.header, ordinal + 1)).offset;
49274
49608
  const start = stream.first + row.offset;
49275
- const parsed = await parseCosRangeValue(stream.data, start, { ...this.options, ...arrays, end });
49609
+ const parsed = await parseCosRangeValue(stream.data, start, { ...this.options, ...arrays, end, onBackingError });
49276
49610
  if (!parsed.value) throw new PdfError("E_PARSE", "Empty compressed object");
49277
49611
  return { objectNumber, generationNumber, value: parsed.value, span: { start, end: parsed.offset } };
49278
49612
  }
49279
49613
  let object;
49280
- let backingFailure;
49281
- const onBackingError = (error) => {
49282
- backingFailure = { error };
49283
- };
49284
49614
  try {
49285
49615
  object = await parseCosRangeObject(this.source, this.repairedOffsets.get(objectNumber) ?? entry.offset, {
49286
49616
  ...this.options,
@@ -49294,10 +49624,11 @@ var PdfObjectReader = class {
49294
49624
  if (object.objectNumber !== objectNumber || object.generationNumber !== generationNumber) throw new PdfError("E_PARSE", "Indirect object identity does not match xref");
49295
49625
  } catch (error) {
49296
49626
  this.options.signal?.throwIfAborted();
49627
+ const backingFailure = this.backingFailures.get(active);
49297
49628
  if (backingFailure && Object.is(backingFailure.error, error)) throw error;
49298
49629
  if (this.options.recovery !== "repair" || !(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
49299
49630
  let recovered;
49300
- for await (const event of scanCosRangeObjects(this.source, { ...this.options, ...arrays })) {
49631
+ for await (const event of scanCosRangeObjects(this.source, { ...this.options, ...arrays, onBackingError })) {
49301
49632
  if (event.kind === "object" && event.object.objectNumber === objectNumber && event.object.generationNumber === generationNumber) recovered = event.object;
49302
49633
  }
49303
49634
  if (!recovered) throw error;
@@ -49363,7 +49694,10 @@ var PdfObjectReader = class {
49363
49694
  active.add(number);
49364
49695
  let dict;
49365
49696
  try {
49366
- dict = await resolvePdfStreamDictionary(object.value, (ref) => this.load(ref.objectNumber, ref.generationNumber, active), active, this.options);
49697
+ dict = await resolvePdfStreamDictionary(object.value, (ref) => this.load(ref.objectNumber, ref.generationNumber, active), active, { ...this.options, onBackingError: (error) => {
49698
+ this.backingFailures.set(active, { error });
49699
+ this.options.onBackingError?.(error);
49700
+ } });
49367
49701
  } finally {
49368
49702
  active.delete(number);
49369
49703
  }
@@ -49449,14 +49783,33 @@ var PdfObjectReader = class {
49449
49783
  }
49450
49784
  };
49451
49785
  async function openPdfObjectReader(source, storage, options = {}) {
49452
- const xrefOptions = { maxNodes: 65536, maxTokenBytes: 1048576, maxRecursionDepth: 100, ...options, ...options.xref };
49786
+ let backingFailure;
49787
+ const callerBackingError = options.onBackingError;
49788
+ const xrefBackingError = options.xref?.onBackingError;
49789
+ const onBackingError = (error) => {
49790
+ backingFailure = { error };
49791
+ callerBackingError?.(error);
49792
+ };
49793
+ options = { ...options, onBackingError };
49794
+ const canRepair = (error) => !(backingFailure && Object.is(backingFailure.error, error)) && error instanceof PdfError && error.code === "E_PARSE";
49795
+ const xrefOptions = {
49796
+ maxNodes: 65536,
49797
+ maxTokenBytes: 1048576,
49798
+ maxRecursionDepth: 100,
49799
+ ...options,
49800
+ ...options.xref,
49801
+ onBackingError(error) {
49802
+ onBackingError(error);
49803
+ if (xrefBackingError !== callerBackingError) xrefBackingError?.(error);
49804
+ }
49805
+ };
49453
49806
  let crossReference;
49454
49807
  let repaired = false;
49455
49808
  try {
49456
49809
  crossReference = await openPdfCrossReference(source, storage, xrefOptions);
49457
49810
  } catch (error) {
49458
49811
  options.signal?.throwIfAborted();
49459
- if (options.recovery !== "repair" || !(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
49812
+ if (options.recovery !== "repair" || !canRepair(error)) throw error;
49460
49813
  crossReference = await recoverPdfReferences(source, storage, xrefOptions);
49461
49814
  repaired = true;
49462
49815
  }
@@ -49471,7 +49824,7 @@ async function openPdfObjectReader(source, storage, options = {}) {
49471
49824
  const pages = root?.value.kind === "dict" && !root.stream ? dictGet(root.value, "Pages") : void 0;
49472
49825
  valid = pages?.kind === "ref" || pages?.kind === "dict";
49473
49826
  } catch (error) {
49474
- if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
49827
+ if (!canRepair(error)) throw error;
49475
49828
  }
49476
49829
  if (!valid) {
49477
49830
  await reader.close();
@@ -49534,7 +49887,7 @@ async function openPdfObjectReader(source, storage, options = {}) {
49534
49887
  try {
49535
49888
  yield* currentReader.objectStreamEntries(object.objectNumber, object.generationNumber);
49536
49889
  } catch (error) {
49537
- if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
49890
+ if (!canRepair(error)) throw error;
49538
49891
  }
49539
49892
  }
49540
49893
  }
@@ -49557,7 +49910,7 @@ async function openPdfObjectReader(source, storage, options = {}) {
49557
49910
  try {
49558
49911
  object = await reader.get(entry.objectNumber, entry.generationNumber ?? 0);
49559
49912
  } catch (error) {
49560
- if (error instanceof PdfError && error.code === "E_PARSE") continue;
49913
+ if (canRepair(error)) continue;
49561
49914
  throw error;
49562
49915
  }
49563
49916
  if (object?.value.kind !== "dict") continue;
@@ -49711,7 +50064,7 @@ async function* parseContentRangeOperators(source, storage, options = {}) {
49711
50064
  }
49712
50065
  if (!Number.isSafeInteger(limits.chunkBytes) || limits.chunkBytes < 8) throw new RangeError("chunkBytes must be at least 8");
49713
50066
  const { signal } = options;
49714
- const lexer = new CosRangeLexer(source, { maxTokenBytes: limits.maxTokenBytes, knownCommands: PDF_KNOWN_COMMANDS, ...options.pathStorage ? { stringStorage: options.pathStorage } : {}, ...signal ? { signal } : {} });
50067
+ 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
50068
  const stack = new PdfOperandStack(storage, limits);
49716
50069
  const backedStack = options.pathStorage ? new StoredMetadataStack(options.pathStorage, signal) : void 0;
49717
50070
  const operands = backedStack ?? stack;
@@ -54597,7 +54950,7 @@ async function resolveRetainedFont(document2, storage, resources, name, options
54597
54950
  }
54598
54951
  let value;
54599
54952
  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 } : {});
54953
+ const retained = await document2.lookup(step.value.node, options.resourceStorage ? { dictionaryStorage: options.resourceStorage, storedDictionaryKeys: ["Font"], storeRootDictionary: step.value.storeRootDictionary ?? false, arrayStorage: options.resourceStorage, storedArrayKeys: ["Widths", "W", "Differences"], storeRootArray: step.value.storeRootArray ?? false } : {});
54601
54954
  value = retained?.value;
54602
54955
  if (retained?.stream) {
54603
54956
  if (retained.value.kind !== "dict" || !retained.reference) throw new PdfError("E_PARSE", "Font stream has no retained identity");
@@ -54606,6 +54959,9 @@ async function resolveRetainedFont(document2, storage, resources, name, options
54606
54959
  identities.set(stream, retained.reference);
54607
54960
  value = stream;
54608
54961
  }
54962
+ } else if (step.value.kind === "dictionary-entry") {
54963
+ const record = await readStoredRecord(step.value.entries.storage, step.value.position, signal);
54964
+ value = cosArray([record.value.key, record.value.value, cosNumber(record.next)]);
54609
54965
  } else if (step.value.kind === "font-encoding") {
54610
54966
  const array = step.value.array;
54611
54967
  value = await StoredFontEncoding.create(() => array.storedItems ? readStoredItems(array.storedItems, signal) : array.items, options.resourceStorage, { onAllocation: (bytes) => allocation.admit(bytes), ...signal ? { signal } : {} });
@@ -57151,122 +57507,6 @@ function resolveDestinationPageIndex(doc, destOrActionNode) {
57151
57507
  return void 0;
57152
57508
  }
57153
57509
 
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
57510
  // packages/pdf-ast/src/extract/retained-form-fields.ts
57271
57511
  import { IntegerTable as IntegerTable4, PagedStorage as PagedStorage6 } from "@poe-platform/safe-fs/storage";
57272
57512
 
@@ -59009,6 +59249,7 @@ async function prepareRetainedPageContent(document2, page2, pageResources, stora
59009
59249
  const request = step.value;
59010
59250
  let result;
59011
59251
  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);
59252
+ else if (request.kind === "dictionary-merge") result = await mergePdfResourceDictionaries(request.destination, request.source, storage, options.signal);
59012
59253
  else if (request.kind === "array-reference") result = cosBool(await memberships.has(request.items, request.objectNumber));
59013
59254
  else if (request.kind === "array-item") {
59014
59255
  const record = await readStoredRecord(request.items.storage, request.position, options.signal);
@@ -60165,6 +60406,7 @@ var PdfRetainedDocument = class _PdfRetainedDocument {
60165
60406
  if (arrayPathPrefix) arrays = {
60166
60407
  ...arrays,
60167
60408
  arrayPathPrefix,
60409
+ ...arrayPathPrefix.length && arrays.storedDictionaryKeys?.includes(arrayPathPrefix[arrayPathPrefix.length - 1]) ? { storeRootDictionary: true } : {},
60168
60410
  ...arrayPathPrefix.length && arrays.storedArrayKeys?.includes(arrayPathPrefix[arrayPathPrefix.length - 1]) ? { storeRootArray: true } : {},
60169
60411
  ...arrayPathPrefix.length && arrays.storedStringKeys?.includes(arrayPathPrefix[arrayPathPrefix.length - 1]) ? { storeRootString: true } : {}
60170
60412
  };
@@ -61688,6 +61930,26 @@ async function* retainedCosObjects(document2, storage, options = {}) {
61688
61930
  yield identity;
61689
61931
  continue;
61690
61932
  }
61933
+ if (options.streamMode && options.streamMode !== "preserve" && object.value.kind === "dict") {
61934
+ const activeSignal = signal ?? new AbortController().signal;
61935
+ const input = document2.objects.decodeStream(entry.objectNumber, generationNumber);
61936
+ const staged2 = options.streamMode === "compress" ? await stageDeflatedPdf(input, storage, activeSignal, maxStreamBytes) : await PdfFileSource.fromStream(storage.fs, storage.directory, input, { signal: activeSignal, maxInputBytes: maxStreamBytes });
61937
+ let failed2 = false;
61938
+ try {
61939
+ const value = { ...object.value, entries: object.value.entries.filter((item) => item.key.decoded !== "Filter" && item.key.decoded !== "DecodeParms") };
61940
+ if (options.streamMode === "compress") dictSet(value, "Filter", cosName("FlateDecode"));
61941
+ dictSet(value, "Length", cosNumber(staged2.size));
61942
+ yield { ...identity, value, stream: { decoded: true, length: staged2.size, chunks: staged2.stream(0, staged2.size, activeSignal) } };
61943
+ } catch (error) {
61944
+ failed2 = true;
61945
+ throw error;
61946
+ } finally {
61947
+ await staged2.close().catch((error) => {
61948
+ if (!failed2) throw error;
61949
+ });
61950
+ }
61951
+ continue;
61952
+ }
61691
61953
  if (options.normalizeContent && object.decoded && object.value.kind === "dict") {
61692
61954
  const decoded2 = await PdfFileSource.fromStream(storage.fs, storage.directory, document2.objects.decodeStream(entry.objectNumber, generationNumber), { ...signal ? { signal } : {}, maxInputBytes: maxStreamBytes });
61693
61955
  let failed2 = false;
@@ -61906,7 +62168,7 @@ async function* saveRetainedDocumentChunks(document2, storage, options = {}) {
61906
62168
  }
61907
62169
  }
61908
62170
  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 })) {
62171
+ 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
62172
  if (!object.stream && object.value.kind === "dict" && dictGet(object.value, "Linearized") !== void 0) mayLinearize = true;
61911
62173
  await objects.set(object);
61912
62174
  }
@@ -62018,8 +62280,208 @@ async function* saveRetainedDocumentChunks(document2, storage, options = {}) {
62018
62280
  }
62019
62281
  }
62020
62282
 
62283
+ // packages/pdf-ast/src/edit/retained-bookmarks.ts
62284
+ import { PagedStorage as PagedStorage13 } from "@poe-platform/safe-fs/storage";
62285
+ async function setRetainedBookmarks(store, storage, root, pageCount, pageReference, bookmarks, signal, maxDepth = Infinity) {
62286
+ if (!pageCount) return;
62287
+ const catalog = await store.get(root.objectNumber);
62288
+ if (catalog?.value.kind !== "dict") return;
62289
+ const frames = new PagedStorage13({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62290
+ const base = frames.allocate(0);
62291
+ let depth = 0, capacity = 0, failed = false, work = 0;
62292
+ async function write(index2, frame) {
62293
+ if (index2 >= capacity) {
62294
+ frames.allocate(24);
62295
+ capacity++;
62296
+ }
62297
+ const bytes = new Uint8Array(24), view = new DataView(bytes.buffer);
62298
+ view.setFloat64(0, frame.number);
62299
+ view.setFloat64(8, frame.last);
62300
+ view.setFloat64(16, frame.count);
62301
+ await frames.write(base + index2 * 24, bytes);
62302
+ }
62303
+ async function read(index2) {
62304
+ const bytes = await frames.read(base + index2 * 24, 24), view = new DataView(bytes.buffer, bytes.byteOffset, bytes.length);
62305
+ return { number: view.getFloat64(0), last: view.getFloat64(8), count: view.getFloat64(16) };
62306
+ }
62307
+ try {
62308
+ for await (const bookmark of bookmarks) {
62309
+ signal.throwIfAborted();
62310
+ if (++work % 64 === 0) {
62311
+ await new Promise((resolve2) => setTimeout(resolve2, 0));
62312
+ signal.throwIfAborted();
62313
+ }
62314
+ if (!Number.isSafeInteger(bookmark.level) || !Number.isSafeInteger(bookmark.pageNumber)) throw new RangeError("Bookmark level and page number must be safe integers");
62315
+ if (!depth) {
62316
+ const outlines = await store.allocate(cosDict({ Type: cosName("Outlines") }));
62317
+ dictSet(catalog.value, "Outlines", outlines);
62318
+ await store.set(catalog);
62319
+ await write(0, { number: outlines.objectNumber, last: 0, count: 0 });
62320
+ depth = 1;
62321
+ }
62322
+ const target = Math.max(1, bookmark.level);
62323
+ depth = Math.min(depth, target);
62324
+ while (depth < target) {
62325
+ const parent2 = await read(depth - 1);
62326
+ if (!parent2.last) break;
62327
+ if (depth >= maxDepth) throw new PdfError("E_LIMIT", "PDF bookmark depth limit exceeded");
62328
+ await write(depth, { number: parent2.last, last: 0, count: 0 });
62329
+ depth++;
62330
+ }
62331
+ const frame = await read(depth - 1), parent = await store.get(frame.number);
62332
+ if (parent.value.kind !== "dict") throw new PdfError("E_PARSE", "Expected outline parent dictionary");
62333
+ const page2 = await pageReference(Math.max(0, Math.min(pageCount - 1, bookmark.pageNumber - 1)));
62334
+ const value = cosDict({ Title: cosString(bookmark.title), Parent: cosRef(frame.number), Dest: cosArray([page2, cosName("XYZ"), { kind: "null" }, { kind: "null" }, { kind: "null" }]) });
62335
+ const item = await store.allocate(value);
62336
+ if (frame.last) {
62337
+ const previous = await store.get(frame.last);
62338
+ if (previous.value.kind !== "dict") throw new PdfError("E_PARSE", "Expected outline sibling dictionary");
62339
+ dictSet(previous.value, "Next", item);
62340
+ await store.set(previous);
62341
+ dictSet(value, "Prev", cosRef(frame.last));
62342
+ await store.set({ objectNumber: item.objectNumber, generationNumber: item.generationNumber, value });
62343
+ } else dictSet(parent.value, "First", item);
62344
+ dictSet(parent.value, "Last", item);
62345
+ dictSet(parent.value, "Count", cosNumber(++frame.count));
62346
+ await store.set(parent);
62347
+ frame.last = item.objectNumber;
62348
+ await write(depth - 1, frame);
62349
+ }
62350
+ } catch (error) {
62351
+ failed = true;
62352
+ throw error;
62353
+ } finally {
62354
+ await frames.close().catch((error) => {
62355
+ if (!failed) throw error;
62356
+ });
62357
+ }
62358
+ }
62359
+
62360
+ // packages/pdf-ast/src/edit/retained-append-attachments.ts
62361
+ async function appendRetainedAttachments(document2, target, storage, attachments, options = {}) {
62362
+ const signal = options.signal ?? new AbortController().signal, appended = new PdfMutableObjectStore(storage, { signal });
62363
+ let failed = false, count = 0;
62364
+ async function resolve2(node) {
62365
+ const found = await document2.lookup(node);
62366
+ return found?.stream ? void 0 : found;
62367
+ }
62368
+ async function save(reference, value) {
62369
+ await target.set({ objectNumber: reference.objectNumber, generationNumber: reference.generationNumber, value });
62370
+ }
62371
+ try {
62372
+ const root = await resolve2(document2.crossReference.rootRef);
62373
+ if (root?.value.kind !== "dict" || !root.reference) return;
62374
+ let owner = root;
62375
+ let names = await resolve2(dictGet(root.value, "Names"));
62376
+ if (names?.value.kind !== "dict") {
62377
+ const value = cosDict({}), reference = await target.allocate(value);
62378
+ names = { value, reference };
62379
+ dictSet(root.value, "Names", reference);
62380
+ await save(root.reference, root.value);
62381
+ }
62382
+ if (names.value.kind !== "dict") throw new Error("Invalid attachment names");
62383
+ if (names.reference) owner = names;
62384
+ let tree = await resolve2(dictGet(names.value, "EmbeddedFiles"));
62385
+ if (tree?.value.kind !== "dict") {
62386
+ const value = cosDict({ Names: cosArray([]) }), reference = await target.allocate(value);
62387
+ tree = { value, reference };
62388
+ dictSet(names.value, "EmbeddedFiles", reference);
62389
+ await save(owner.reference, owner.value);
62390
+ }
62391
+ if (tree.value.kind !== "dict") throw new Error("Invalid attachment tree");
62392
+ if (tree.reference) owner = tree;
62393
+ const existing = await resolve2(dictGet(tree.value, "Names")), namesMarker = cosArray([]);
62394
+ if (existing?.value.kind === "array" && existing.reference) owner = { value: namesMarker, reference: existing.reference };
62395
+ else dictSet(tree.value, "Names", namesMarker);
62396
+ let pageOwner, previousAnnots;
62397
+ const annotsMarker = cosArray([]);
62398
+ if (options.pageIndex !== void 0) for await (const page2 of document2.pages()) {
62399
+ if (page2.index !== options.pageIndex) continue;
62400
+ if (page2.reference) {
62401
+ const annots = await resolve2(dictGet(page2.dict, "Annots"));
62402
+ previousAnnots = annots?.value.kind === "array" ? annots.value : void 0;
62403
+ if (annots?.value.kind === "array" && annots.reference) pageOwner = { value: annotsMarker, reference: annots.reference };
62404
+ else {
62405
+ dictSet(page2.dict, "Annots", annotsMarker);
62406
+ pageOwner = { value: page2.dict, reference: page2.reference };
62407
+ }
62408
+ }
62409
+ break;
62410
+ }
62411
+ for await (const attachment of attachments) {
62412
+ signal.throwIfAborted();
62413
+ const compressed = await stageDeflatedPdf(attachment.chunks, storage, signal);
62414
+ let itemFailed = false;
62415
+ try {
62416
+ const embedded = await target.allocate();
62417
+ 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) } });
62418
+ const reference = await target.allocate(cosDict({ Type: cosName("Filespec"), F: cosString(attachment.filename), UF: cosString(attachment.filename), EF: cosDict({ F: embedded }) }));
62419
+ let annotation;
62420
+ 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))) }));
62421
+ await appended.set({ objectNumber: ++count, generationNumber: 0, value: cosArray([cosString(attachment.filename), reference, ...annotation ? [annotation] : []]) });
62422
+ } catch (error) {
62423
+ itemFailed = true;
62424
+ throw error;
62425
+ } finally {
62426
+ await compressed.close().catch((error) => {
62427
+ if (!itemFailed) throw error;
62428
+ });
62429
+ }
62430
+ }
62431
+ const encoder = new TextEncoder();
62432
+ async function* serialized(node) {
62433
+ signal.throwIfAborted();
62434
+ if (node === namesMarker || node === annotsMarker) {
62435
+ yield encoder.encode("[ ");
62436
+ const old = node === namesMarker ? existing?.value : previousAnnots;
62437
+ if (old?.kind === "array") for (const item of old.items) {
62438
+ yield* serializeCosNodeChunks(item, { signal });
62439
+ yield encoder.encode(" ");
62440
+ }
62441
+ for await (const pair of appended.objects()) {
62442
+ if (pair.value.kind !== "array") throw new Error("Invalid attachment pair");
62443
+ const items = node === namesMarker ? pair.value.items.slice(0, 2) : pair.value.items.slice(2);
62444
+ for (const item of items) {
62445
+ yield* serializeCosNodeChunks(item, { signal });
62446
+ yield encoder.encode(" ");
62447
+ }
62448
+ }
62449
+ yield encoder.encode("]");
62450
+ } else if (node.kind === "dict") {
62451
+ yield encoder.encode("<<\n");
62452
+ for (const entry of node.entries) {
62453
+ yield* serializeCosNodeChunks(entry.key, { signal });
62454
+ yield encoder.encode(" ");
62455
+ yield* serialized(entry.value);
62456
+ yield encoder.encode("\n");
62457
+ }
62458
+ yield encoder.encode(">>");
62459
+ } else if (node.kind === "array") {
62460
+ yield encoder.encode("[ ");
62461
+ for (const item of node.items) {
62462
+ yield* serialized(item);
62463
+ yield encoder.encode(" ");
62464
+ }
62465
+ yield encoder.encode("]");
62466
+ } else yield* serializeCosNodeChunks(node, { signal });
62467
+ }
62468
+ for (const edited of [owner, ...pageOwner && count ? [pageOwner] : []]) {
62469
+ let length = 0;
62470
+ for await (const bytes of serialized(edited.value)) length += bytes.length;
62471
+ await target.setSerializedValue({ objectNumber: edited.reference.objectNumber, generationNumber: edited.reference.generationNumber, body: { length, chunks: serialized(edited.value) } });
62472
+ }
62473
+ } catch (error) {
62474
+ failed = true;
62475
+ throw error;
62476
+ } finally {
62477
+ await appended.close().catch((error) => {
62478
+ if (!failed) throw error;
62479
+ });
62480
+ }
62481
+ }
62482
+
62021
62483
  // packages/pdf-ast/src/edit/retained-form-appearances.ts
62022
- import { IntegerTable as IntegerTable8, PagedStorage as PagedStorage13 } from "@poe-platform/safe-fs/storage";
62484
+ import { IntegerTable as IntegerTable8, PagedStorage as PagedStorage14 } from "@poe-platform/safe-fs/storage";
62023
62485
 
62024
62486
  // packages/pdf-ast/src/edit/form-appearance-chunks.ts
62025
62487
  function* serializeFormAppearanceChunks(text, options) {
@@ -62107,7 +62569,7 @@ function* operators(text, options) {
62107
62569
  // packages/pdf-ast/src/edit/retained-form-appearances.ts
62108
62570
  async function generateRetainedFormAppearances(document2, store, storage, signal) {
62109
62571
  if (!document2.crossReference.rootRef) return;
62110
- const backing = new PagedStorage13({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), active = new IntegerTable8(backing);
62572
+ const backing = new PagedStorage14({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), active = new IntegerTable8(backing);
62111
62573
  let head = -1, failed = false, work = 0;
62112
62574
  let defaultAppearance;
62113
62575
  async function checkpoint(depth = 0) {
@@ -62314,16 +62776,16 @@ async function generateRetainedFormAppearances(document2, store, storage, signal
62314
62776
  }
62315
62777
 
62316
62778
  // packages/pdf-ast/src/edit/retained-flatten-annotations.ts
62317
- import { IntegerTable as IntegerTable10, PagedStorage as PagedStorage17 } from "@poe-platform/safe-fs/storage";
62779
+ import { IntegerTable as IntegerTable10, PagedStorage as PagedStorage18 } from "@poe-platform/safe-fs/storage";
62318
62780
 
62319
62781
  // packages/pdf-ast/src/edit/retained-content-edit.ts
62320
- import { IntegerTable as IntegerTable9, PagedStorage as PagedStorage14 } from "@poe-platform/safe-fs/storage";
62782
+ import { IntegerTable as IntegerTable9, PagedStorage as PagedStorage15 } from "@poe-platform/safe-fs/storage";
62321
62783
  var RetainedContentEditor = class _RetainedContentEditor {
62322
62784
  constructor(store, storage, signal) {
62323
62785
  this.store = store;
62324
62786
  this.storage = storage;
62325
62787
  this.signal = signal;
62326
- this.backing = new PagedStorage14({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62788
+ this.backing = new PagedStorage15({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62327
62789
  this.counts = new IntegerTable9(this.backing);
62328
62790
  this.identities = new PdfNameIndex(storage, Infinity, signal);
62329
62791
  }
@@ -62364,6 +62826,12 @@ var RetainedContentEditor = class _RetainedContentEditor {
62364
62826
  await this.count(value, 1n);
62365
62827
  await this.store.set({ objectNumber: reference.objectNumber, generationNumber: reference.generationNumber, value, ...stream ? { stream } : {} });
62366
62828
  }
62829
+ async setSerialized(reference, body, values) {
62830
+ const old = await this.store.get(reference.objectNumber);
62831
+ if (old) await this.count(old.value, -1n);
62832
+ for await (const node of values) await this.count(node, 1n);
62833
+ await this.store.setSerializedValue({ objectNumber: reference.objectNumber, generationNumber: reference.generationNumber, body });
62834
+ }
62367
62835
  async replace(page2, chunks, compress = true) {
62368
62836
  const source = compress ? await stageDeflatedPdf(chunks, this.storage, this.signal) : await PdfFileSource.fromStream(this.storage.fs, this.storage.directory, chunks, { signal: this.signal });
62369
62837
  let failed = false;
@@ -62389,14 +62857,14 @@ var RetainedContentEditor = class _RetainedContentEditor {
62389
62857
  };
62390
62858
 
62391
62859
  // packages/pdf-ast/src/edit/retained-name-replacement.ts
62392
- import { PagedStorage as PagedStorage15 } from "@poe-platform/safe-fs/storage";
62860
+ import { PagedStorage as PagedStorage16 } from "@poe-platform/safe-fs/storage";
62393
62861
  async function* replaceRetainedPdfName(input, oldName, newName, storage, options = {}) {
62394
62862
  const chunkBytes = options.chunkBytes ?? 16384, maximum10 = options.maxOutputBytes ?? Infinity;
62395
62863
  if (!Number.isSafeInteger(chunkBytes) || chunkBytes < 1) throw new RangeError("Invalid name replacement chunk size");
62396
62864
  if (maximum10 !== Infinity && (!Number.isSafeInteger(maximum10) || maximum10 < 0)) throw new RangeError("Invalid name replacement output limit");
62397
62865
  const signal = options.signal ?? new AbortController().signal;
62398
62866
  signal.throwIfAborted();
62399
- const table = new PagedStorage15({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), length = oldName.length + 1;
62867
+ const table = new PagedStorage16({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), length = oldName.length + 1;
62400
62868
  const base = table.allocate(length * 8), record = new Uint8Array(8), view = new DataView(record.buffer);
62401
62869
  const pattern = (at) => at ? oldName.charCodeAt(at - 1) : 47;
62402
62870
  let buffer = new Uint8Array(chunkBytes), used = 0, total = 0, work = 0, failed = false;
@@ -62474,10 +62942,10 @@ async function* replaceRetainedPdfName(input, oldName, newName, storage, options
62474
62942
  }
62475
62943
 
62476
62944
  // packages/pdf-ast/src/edit/retained-draw-text.ts
62477
- import { PagedStorage as PagedStorage16 } from "@poe-platform/safe-fs/storage";
62945
+ import { PagedStorage as PagedStorage17 } from "@poe-platform/safe-fs/storage";
62478
62946
  async function drawRetainedAnnotationText(page2, editor, storage, text, x, y, isolated, font, signal) {
62479
62947
  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);
62948
+ const backing = new PagedStorage17({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62481
62949
  let failed = false;
62482
62950
  try {
62483
62951
  const name = await font(), position = backing.allocate(text.length);
@@ -62553,7 +63021,7 @@ async function flattenRetainedAnnotations(document2, store, storage, mode, signa
62553
63021
  for await (const page2 of document2.pages()) {
62554
63022
  const annotations = await array(dictGet(page2.dict, "Annots"));
62555
63023
  if (!annotations) continue;
62556
- const survivorStorage = new PagedStorage17({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63024
+ const survivorStorage = new PagedStorage18({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62557
63025
  const survivorBase = survivorStorage.allocate(0);
62558
63026
  let pageFailed = false;
62559
63027
  try {
@@ -62639,7 +63107,7 @@ async function flattenRetainedAnnotations(document2, store, storage, mode, signa
62639
63107
  }
62640
63108
  if (normal?.stream && normal.reference && normal.value.kind === "dict") {
62641
63109
  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);
63110
+ const backing = new PagedStorage18({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), renames = new IntegerTable10(backing), names = new PdfNameIndex(storage, Infinity, signal);
62643
63111
  let appearanceFailed = false, count = 0;
62644
63112
  try {
62645
63113
  if (content.size) {
@@ -62757,8 +63225,294 @@ q ${scaleX} 0 0 ${scaleY} ${tx} ${ty} cm${matSuffix}
62757
63225
  }
62758
63226
  }
62759
63227
 
63228
+ // packages/pdf-ast/src/edit/retained-name-map.ts
63229
+ import { PagedStorage as PagedStorage19 } from "@poe-platform/safe-fs/storage";
63230
+ async function* replaceRetainedPdfNames(input, names, storage, options = {}) {
63231
+ const signal = options.signal ?? new AbortController().signal, size = options.chunkBytes ?? 16384;
63232
+ if (!Number.isSafeInteger(size) || size < 1) throw new RangeError("Invalid name replacement chunk size");
63233
+ const trie = new PagedStorage19({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), pending = new PagedStorage19({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63234
+ const root = trie.allocate(40), prefixBase = pending.allocate(0);
63235
+ let output = new Uint8Array(size), used = 0, failed = false, work = 0;
63236
+ const body = (byte3) => byte3 >= 48 && byte3 <= 57 || byte3 >= 65 && byte3 <= 90 || byte3 >= 97 && byte3 <= 122 || [95, 46, 43, 45].includes(byte3);
63237
+ async function checkpoint() {
63238
+ signal.throwIfAborted();
63239
+ if (++work % 16384 === 0) await new Promise((resolve2) => setTimeout(resolve2, 0));
63240
+ }
63241
+ async function get(at) {
63242
+ const bytes = await trie.read(at, 40);
63243
+ return new DataView(bytes.buffer, bytes.byteOffset, bytes.length);
63244
+ }
63245
+ async function put(at, row) {
63246
+ await trie.write(at, new Uint8Array(row.buffer, row.byteOffset, row.byteLength));
63247
+ }
63248
+ async function child(at, byte3, create) {
63249
+ const parent = await get(at);
63250
+ let current = parent.getFloat64(0);
63251
+ while (current) {
63252
+ const row2 = await get(current);
63253
+ if (row2.getFloat64(16) === byte3) return current;
63254
+ current = row2.getFloat64(8);
63255
+ }
63256
+ if (!create) return;
63257
+ const next = trie.allocate(40), row = new DataView(new ArrayBuffer(40));
63258
+ row.setFloat64(8, parent.getFloat64(0));
63259
+ row.setFloat64(16, byte3);
63260
+ await put(next, row);
63261
+ parent.setFloat64(0, next);
63262
+ await put(at, parent);
63263
+ return next;
63264
+ }
63265
+ function emit(byte3) {
63266
+ output[used++] = byte3;
63267
+ if (used === size) {
63268
+ const full = output;
63269
+ output = new Uint8Array(size);
63270
+ used = 0;
63271
+ return full;
63272
+ }
63273
+ }
63274
+ async function* replay(store, start, length) {
63275
+ for (let at = 0; at < length; at += size) for (const byte3 of await store.read(start + at, Math.min(size, length - at))) {
63276
+ await checkpoint();
63277
+ const full = emit(byte3);
63278
+ if (full) yield full;
63279
+ }
63280
+ }
63281
+ try {
63282
+ for await (const [name, replacement] of names) {
63283
+ let node2 = root, valid = true;
63284
+ for (let i = 0; i < name.length; i++) {
63285
+ await checkpoint();
63286
+ if (!body(name.charCodeAt(i))) {
63287
+ valid = false;
63288
+ break;
63289
+ }
63290
+ node2 = await child(node2, name.charCodeAt(i), true);
63291
+ }
63292
+ if (!valid) continue;
63293
+ const start = trie.allocate(replacement.length), row = await get(node2);
63294
+ row.setFloat64(24, start + 1);
63295
+ row.setFloat64(32, replacement.length);
63296
+ await put(node2, row);
63297
+ for (let at = 0; at < replacement.length; at += size) {
63298
+ const bytes = new Uint8Array(Math.min(size, replacement.length - at));
63299
+ for (let i = 0; i < bytes.length; i++) bytes[i] = replacement.charCodeAt(at + i);
63300
+ await trie.write(start + at, bytes);
63301
+ }
63302
+ }
63303
+ let matching = false, node = root, length = 0, capacity = 0, buffered = 0;
63304
+ const prefix = new Uint8Array(size);
63305
+ async function flushPrefix() {
63306
+ if (buffered) {
63307
+ if (length > capacity) {
63308
+ pending.allocate(length - capacity);
63309
+ capacity = length;
63310
+ }
63311
+ await pending.write(prefixBase + length - buffered, prefix.subarray(0, buffered));
63312
+ buffered = 0;
63313
+ }
63314
+ }
63315
+ async function* finish() {
63316
+ await flushPrefix();
63317
+ const row = await get(node), replacement = row.getFloat64(24);
63318
+ const slash = emit(47);
63319
+ if (slash) yield slash;
63320
+ if (replacement) yield* replay(trie, replacement - 1, row.getFloat64(32));
63321
+ else yield* replay(pending, prefixBase, length);
63322
+ matching = false;
63323
+ }
63324
+ for await (const bytes of input) for (const byte3 of bytes) {
63325
+ await checkpoint();
63326
+ if (matching && body(byte3)) {
63327
+ const next = await child(node, byte3, false);
63328
+ if (next !== void 0) {
63329
+ node = next;
63330
+ prefix[buffered++] = byte3;
63331
+ length++;
63332
+ if (buffered === size) await flushPrefix();
63333
+ continue;
63334
+ }
63335
+ await flushPrefix();
63336
+ const slash = emit(47);
63337
+ if (slash) yield slash;
63338
+ yield* replay(pending, prefixBase, length);
63339
+ matching = false;
63340
+ } else if (matching) yield* finish();
63341
+ if (byte3 === 47) {
63342
+ matching = true;
63343
+ node = root;
63344
+ length = 0;
63345
+ buffered = 0;
63346
+ } else {
63347
+ const full = emit(byte3);
63348
+ if (full) yield full;
63349
+ }
63350
+ }
63351
+ if (matching) yield* finish();
63352
+ if (used) yield output.subarray(0, used);
63353
+ } catch (error) {
63354
+ failed = true;
63355
+ throw error;
63356
+ } finally {
63357
+ const results = await Promise.allSettled([trie.close(), pending.close()]);
63358
+ if (!failed) {
63359
+ for (const result of results) if (result.status === "rejected") await Promise.reject(result.reason);
63360
+ }
63361
+ }
63362
+ }
63363
+
63364
+ // packages/pdf-ast/src/edit/retained-preserve-stamp.ts
63365
+ async function preserveRetainedStamp(document2, source, page2, other, store, editor, storage, clone, mode, signal) {
63366
+ const renames = new PdfMutableObjectStore(storage, { signal }), additions = new PdfMutableObjectStore(storage, { signal });
63367
+ let addedCount = 0, count = 0, failed = false, work = 0;
63368
+ const owners = /* @__PURE__ */ new Map();
63369
+ const key = (ref) => `${ref.objectNumber}:${ref.generationNumber}`;
63370
+ if (page2.reference) owners.set(key(page2.reference), { reference: page2.reference, value: page2.dict });
63371
+ async function checkpoint() {
63372
+ signal.throwIfAborted();
63373
+ if (++work % 64 === 0) await new Promise((resolve2) => setTimeout(resolve2, 0));
63374
+ }
63375
+ async function dictionary(node) {
63376
+ const cached = node?.kind === "ref" ? owners.get(key(node)) : void 0;
63377
+ if (cached) return cached;
63378
+ const found = await document2.lookup(node);
63379
+ if (found?.stream || found?.value.kind !== "dict") return;
63380
+ const result = { ...found, value: found.value };
63381
+ if (result.reference) owners.set(key(result.reference), { reference: result.reference, value: result.value });
63382
+ return result;
63383
+ }
63384
+ async function stream(chunks) {
63385
+ const staged = await PdfFileSource.fromStream(storage.fs, storage.directory, chunks, { signal });
63386
+ let failed2 = false;
63387
+ try {
63388
+ const reference = await store.allocate();
63389
+ await editor.set(reference, cosDict({ Length: cosNumber(staged.size) }), { decoded: true, length: staged.size, chunks: staged.stream(0, staged.size, signal) });
63390
+ return reference;
63391
+ } catch (error) {
63392
+ failed2 = true;
63393
+ throw error;
63394
+ } finally {
63395
+ await staged.close().catch((error) => {
63396
+ if (!failed2) throw error;
63397
+ });
63398
+ }
63399
+ }
63400
+ async function* mappings() {
63401
+ for await (const object of renames.objects()) if (object.value.kind === "array" && object.value.items[0]?.kind === "string" && object.value.items[1]?.kind === "string") {
63402
+ const [name, replacement] = object.value.items;
63403
+ yield [decodePdfString(name), decodePdfString(replacement)];
63404
+ }
63405
+ }
63406
+ try {
63407
+ const dstAttributes = await page2.attributes(), srcAttributes = await other.attributes();
63408
+ let resources = await dictionary(dictGet(page2.dict, "Resources"));
63409
+ if (!resources) {
63410
+ const entries = [];
63411
+ for (const entry of dstAttributes.resources.entries) {
63412
+ const sub = await document2.lookup(entry.value);
63413
+ 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 });
63414
+ }
63415
+ resources = { value: { kind: "dict", entries } };
63416
+ dictSet(page2.dict, "Resources", resources.value);
63417
+ }
63418
+ for (const category of ["Font", "XObject", "ExtGState", "ColorSpace", "Pattern", "Shading", "Properties"]) {
63419
+ const src = await source.lookup(dictGet(srcAttributes.resources, category));
63420
+ if (src?.stream || src?.value.kind !== "dict") continue;
63421
+ let dst = await dictionary(dictGet(resources.value, category));
63422
+ if (!dst) {
63423
+ dst = { value: cosDict({}) };
63424
+ dictSet(resources.value, category, dst.value);
63425
+ }
63426
+ for (const entry of src.value.entries) {
63427
+ await checkpoint();
63428
+ const value = await clone(entry.value), original = entry.key.decoded;
63429
+ let name = original;
63430
+ if (dictGet(dst.value, original)) {
63431
+ name = `Ov_${page2.index}_${original}`;
63432
+ let suffix = 1;
63433
+ while (dictGet(dst.value, name)) {
63434
+ await checkpoint();
63435
+ name = `Ov_${page2.index}_${suffix++}_${original}`;
63436
+ }
63437
+ await renames.set({ objectNumber: ++count, generationNumber: 0, value: cosArray([cosString(original), cosString(name)]) });
63438
+ }
63439
+ dictSet(dst.value, name, value);
63440
+ }
63441
+ }
63442
+ for (const owner of owners.values()) await editor.set(owner.reference, owner.value);
63443
+ const contents = dictGet(other.dict, "Contents");
63444
+ if (!contents) return;
63445
+ const resolved = await source.lookup(contents), nodes = resolved?.value.kind === "array" && !resolved.stream ? resolved.value.items : [contents];
63446
+ for (const node of nodes) {
63447
+ await checkpoint();
63448
+ const found = await source.lookup(node);
63449
+ 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);
63450
+ await additions.set({ objectNumber: ++addedCount, generationNumber: 0, value: added });
63451
+ }
63452
+ if (!addedCount) return;
63453
+ const previous = dictGet(page2.dict, "Contents"), resolvedPrevious = previous && await document2.lookup(previous);
63454
+ const before = resolvedPrevious?.value.kind === "array" && !resolvedPrevious.stream ? resolvedPrevious.value.items : previous ? [previous] : [];
63455
+ const encoder = new TextEncoder();
63456
+ async function* text(value) {
63457
+ yield encoder.encode(value);
63458
+ }
63459
+ const openTarget = await stream(text("q\n")), openSource = await stream(text(retainedStampTransform(dstAttributes, srcAttributes))), close = await stream(text("\nQ\n"));
63460
+ const marker2 = cosArray([]);
63461
+ dictSet(page2.dict, "Contents", marker2);
63462
+ async function* contentNodes() {
63463
+ for (const overlay of mode === "underlay" ? [true, false] : [false, true]) {
63464
+ yield overlay ? openSource : openTarget;
63465
+ if (overlay) {
63466
+ for await (const object of additions.objects()) {
63467
+ await checkpoint();
63468
+ yield object.value;
63469
+ }
63470
+ } else for (const node of before) {
63471
+ await checkpoint();
63472
+ yield node;
63473
+ }
63474
+ yield close;
63475
+ }
63476
+ }
63477
+ async function* body() {
63478
+ yield encoder.encode("<<\n");
63479
+ for (const entry of page2.dict.entries) {
63480
+ yield* serializeCosNodeChunks(entry.key, { signal });
63481
+ yield encoder.encode(" ");
63482
+ if (entry.value === marker2) {
63483
+ yield encoder.encode("[ ");
63484
+ for await (const node of contentNodes()) {
63485
+ yield* serializeCosNodeChunks(node, { signal });
63486
+ yield encoder.encode(" ");
63487
+ }
63488
+ yield encoder.encode("]");
63489
+ } else yield* serializeCosNodeChunks(entry.value, { signal });
63490
+ yield encoder.encode("\n");
63491
+ }
63492
+ yield encoder.encode(">>");
63493
+ }
63494
+ async function* values() {
63495
+ yield page2.dict;
63496
+ yield* contentNodes();
63497
+ }
63498
+ if (page2.reference) {
63499
+ let length = 0;
63500
+ for await (const bytes of body()) length += bytes.length;
63501
+ await editor.setSerialized(page2.reference, { length, chunks: body() }, values());
63502
+ }
63503
+ } catch (error) {
63504
+ failed = true;
63505
+ throw error;
63506
+ } finally {
63507
+ const results = await Promise.allSettled([renames.close(), additions.close()]);
63508
+ if (!failed) {
63509
+ for (const result of results) if (result.status === "rejected") await Promise.reject(result.reason);
63510
+ }
63511
+ }
63512
+ }
63513
+
62760
63514
  // packages/pdf-ast/src/edit/retained-stamps.ts
62761
- import { IntegerTable as IntegerTable11, PagedStorage as PagedStorage18 } from "@poe-platform/safe-fs/storage";
63515
+ import { IntegerTable as IntegerTable11, PagedStorage as PagedStorage20 } from "@poe-platform/safe-fs/storage";
62762
63516
  async function stampRetainedPages(document2, store, storage, getPage, stamps, signal) {
62763
63517
  const editor = await RetainedContentEditor.open(store, storage, signal);
62764
63518
  let counter = 1, failed = false, work = 0;
@@ -62769,7 +63523,7 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62769
63523
  try {
62770
63524
  for await (const stamp of stamps) {
62771
63525
  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);
63526
+ const backing = new PagedStorage20({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), memo = new IntegerTable11(backing);
62773
63527
  let stampFailed = false;
62774
63528
  async function clone(node, depth = 0) {
62775
63529
  await checkpoint();
@@ -62779,7 +63533,12 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62779
63533
  if (found !== void 0) return cosRef(Number(found));
62780
63534
  const identity = await source.document.crossReference.index.get(node.objectNumber, signal);
62781
63535
  const object = identity ? await source.document.objects.get(node.objectNumber, identity.generationNumber ?? 0) : void 0;
62782
- if (!object) return { kind: "null" };
63536
+ if (!object) {
63537
+ if (!stamp.preserveStreams) return { kind: "null" };
63538
+ const reference2 = await store.allocate(cosDict({}));
63539
+ await memo.set(BigInt(node.objectNumber), BigInt(reference2.objectNumber));
63540
+ return reference2;
63541
+ }
62783
63542
  const reference = await store.allocate({ kind: "null" });
62784
63543
  await memo.set(BigInt(node.objectNumber), BigInt(reference.objectNumber));
62785
63544
  const value = await clone(object.value, depth + 1);
@@ -62798,6 +63557,11 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62798
63557
  if (node.kind === "dict") {
62799
63558
  const entries = [];
62800
63559
  for (const entry of node.entries) if (entry.key.decoded !== "Parent") entries.push({ key: { ...entry.key }, value: await clone(entry.value, depth + 1) });
63560
+ if (stamp.preserveStreams) {
63561
+ const dict = cosDict({});
63562
+ for (const entry of entries) dictSet(dict, entry.key.decoded, entry.value);
63563
+ return dict;
63564
+ }
62801
63565
  return { kind: "dict", entries };
62802
63566
  }
62803
63567
  return node;
@@ -62806,6 +63570,10 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62806
63570
  for await (const pair of stamp.pages) {
62807
63571
  await checkpoint();
62808
63572
  const page2 = await getPage(pair.targetIndex), other = await source.getPage(pair.sourceIndex);
63573
+ if (stamp.preserveStreams) {
63574
+ await preserveRetainedStamp(document2, source.document, page2, other, store, editor, storage, clone, stamp.mode, signal);
63575
+ continue;
63576
+ }
62809
63577
  const target = await PdfFileSource.fromStream(storage.fs, storage.directory, page2.streamContents(), { signal });
62810
63578
  let content, pageFailed = false;
62811
63579
  try {
@@ -62859,43 +63627,7 @@ async function stampRetainedPages(document2, store, storage, getPage, stamps, si
62859
63627
  }
62860
63628
  }
62861
63629
  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
- }
63630
+ const stampOpenStr = retainedStampTransform(dstAttributes, srcAttributes);
62899
63631
  const encoder = new TextEncoder(), stamped = content;
62900
63632
  async function* contents() {
62901
63633
  for (const isStamp of stamp.mode === "underlay" ? [true, false] : [false, true]) {
@@ -62935,14 +63667,54 @@ ${fmt6(s)} 0 0 ${fmt6(s)} ${fmt4(tx)} ${fmt4(ty)} cm
62935
63667
  });
62936
63668
  }
62937
63669
  }
63670
+ function retainedStampTransform(dstAttributes, srcAttributes) {
63671
+ const dstSize = { width: Math.abs(dstAttributes.mediaBox[2] - dstAttributes.mediaBox[0]), height: Math.abs(dstAttributes.mediaBox[3] - dstAttributes.mediaBox[1]) };
63672
+ const srcSize = { width: Math.abs(srcAttributes.mediaBox[2] - srcAttributes.mediaBox[0]), height: Math.abs(srcAttributes.mediaBox[3] - srcAttributes.mediaBox[1]) };
63673
+ const rotDiff = ((dstAttributes.rotation - srcAttributes.rotation) % 360 + 360) % 360;
63674
+ let stampOpenStr = "q\n";
63675
+ if (srcSize.width > 0 && srcSize.height > 0) {
63676
+ const fmt6 = (n) => Number(n.toFixed(6));
63677
+ const fmt4 = (n) => Number(n.toFixed(4));
63678
+ if (rotDiff === 90) {
63679
+ const s = Math.min(dstSize.height / srcSize.width, dstSize.width / srcSize.height);
63680
+ const ox = (dstSize.height - srcSize.width * s) / 2;
63681
+ const oy = (dstSize.width - srcSize.height * s) / 2;
63682
+ stampOpenStr = `q
63683
+ 0 ${fmt6(s)} ${fmt6(-s)} 0 ${fmt4(dstSize.width - oy)} ${fmt4(ox)} cm
63684
+ `;
63685
+ } else if (rotDiff === 180) {
63686
+ const s = Math.min(dstSize.width / srcSize.width, dstSize.height / srcSize.height);
63687
+ const ox = (dstSize.width - srcSize.width * s) / 2;
63688
+ const oy = (dstSize.height - srcSize.height * s) / 2;
63689
+ stampOpenStr = `q
63690
+ ${fmt6(-s)} 0 0 ${fmt6(-s)} ${fmt4(dstSize.width - ox)} ${fmt4(dstSize.height - oy)} cm
63691
+ `;
63692
+ } else if (rotDiff === 270) {
63693
+ const s = Math.min(dstSize.height / srcSize.width, dstSize.width / srcSize.height);
63694
+ const ox = (dstSize.height - srcSize.width * s) / 2;
63695
+ const oy = (dstSize.width - srcSize.height * s) / 2;
63696
+ stampOpenStr = `q
63697
+ 0 ${fmt6(-s)} ${fmt6(s)} 0 ${fmt4(oy)} ${fmt4(dstSize.height - ox)} cm
63698
+ `;
63699
+ } else if (Math.abs(srcSize.width - dstSize.width) > 0.5 || Math.abs(srcSize.height - dstSize.height) > 0.5) {
63700
+ const s = Math.min(dstSize.width / srcSize.width, dstSize.height / srcSize.height);
63701
+ const tx = (dstSize.width - srcSize.width * s) / 2;
63702
+ const ty = (dstSize.height - srcSize.height * s) / 2;
63703
+ stampOpenStr = `q
63704
+ ${fmt6(s)} 0 0 ${fmt6(s)} ${fmt4(tx)} ${fmt4(ty)} cm
63705
+ `;
63706
+ }
63707
+ }
63708
+ return stampOpenStr;
63709
+ }
62938
63710
 
62939
63711
  // packages/pdf-ast/src/edit/retained-inline-images.ts
62940
- import { PagedStorage as PagedStorage19 } from "@poe-platform/safe-fs/storage";
63712
+ import { PagedStorage as PagedStorage21 } from "@poe-platform/safe-fs/storage";
62941
63713
  async function externalizeRetainedInlineImages(document2, store, storage, options, signal) {
62942
63714
  const minimum = options.minBytes ?? 1024;
62943
63715
  if (!Number.isSafeInteger(minimum) || minimum < 0) throw new RangeError("Invalid inline-image minimum size");
62944
63716
  const editor = await RetainedContentEditor.open(store, storage, signal);
62945
- const paths = new PagedStorage19({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63717
+ const paths = new PagedStorage21({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
62946
63718
  const keys = { BPC: "BitsPerComponent", CS: "ColorSpace", D: "Decode", DP: "DecodeParms", F: "Filter", H: "Height", IM: "ImageMask", I: "Interpolate", W: "Width" };
62947
63719
  const colors = { G: "DeviceGray", RGB: "DeviceRGB", CMYK: "DeviceCMYK", I: "Indexed" };
62948
63720
  const filters = { AHx: "ASCIIHexDecode", A85: "ASCII85Decode", LZW: "LZWDecode", Fl: "FlateDecode", RL: "RunLengthDecode", CCF: "CCITTFaxDecode", DCT: "DCTDecode" };
@@ -63034,7 +63806,7 @@ async function externalizeRetainedInlineImages(document2, store, storage, option
63034
63806
  }
63035
63807
 
63036
63808
  // packages/pdf-ast/src/edit/retained-resource-pruning.ts
63037
- import { IntegerTable as IntegerTable12, PagedStorage as PagedStorage20 } from "@poe-platform/safe-fs/storage";
63809
+ import { IntegerTable as IntegerTable12, PagedStorage as PagedStorage22 } from "@poe-platform/safe-fs/storage";
63038
63810
  async function collectNames(input, names, found, signal) {
63039
63811
  const iterator = input[Symbol.asyncIterator](), pending = [];
63040
63812
  let chunk = new Uint8Array(), at = 0, ended = false, changed = false, work = 0, failed = false;
@@ -63116,7 +63888,7 @@ async function pruneRetainedResources(document2, store, storage, signal) {
63116
63888
  return { ...found2, value: same(page2.reference) ? page2.dict : same(resources?.reference) ? resources.value : found2.value };
63117
63889
  }
63118
63890
  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);
63891
+ const backing = new PagedStorage22({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), found = new IntegerTable12(backing);
63120
63892
  let failed = false;
63121
63893
  try {
63122
63894
  const referenced = async (name) => await found.get(BigInt((await names.intern(name)).index)) !== void 0;
@@ -63246,7 +64018,7 @@ async function flattenRetainedRotations(document2, store, storage, signal) {
63246
64018
  }
63247
64019
 
63248
64020
  // packages/pdf-ast/src/edit/retained-attachment-edits.ts
63249
- import { IntegerTable as IntegerTable13, PagedStorage as PagedStorage21 } from "@poe-platform/safe-fs/storage";
64021
+ import { IntegerTable as IntegerTable13, PagedStorage as PagedStorage23 } from "@poe-platform/safe-fs/storage";
63250
64022
  var PdfDuplicateAttachment = class extends PdfError {
63251
64023
  constructor(key) {
63252
64024
  super("E_CAPABILITY", `Duplicate attachment key: ${key}`);
@@ -63257,7 +64029,7 @@ var PdfDuplicateAttachment = class extends PdfError {
63257
64029
  async function editRetainedAttachments(document2, target, storage, remove, additions, signal, preserveTree = false) {
63258
64030
  const pairs = new PdfMutableObjectStore(storage, { signal });
63259
64031
  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);
64032
+ const backing = new PagedStorage23({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4), first = new IntegerTable13(backing), removals = new IntegerTable13(backing);
63261
64033
  let failed = false, count = 0, work = 0;
63262
64034
  async function checkpoint() {
63263
64035
  signal.throwIfAborted();
@@ -63459,13 +64231,13 @@ async function* retainedAttachmentNameTokens(document2, storage, root, signal, r
63459
64231
  }
63460
64232
 
63461
64233
  // packages/pdf-ast/src/edit/retained-graph.ts
63462
- import { PagedStorage as PagedStorage22 } from "@poe-platform/safe-fs/storage";
64234
+ import { PagedStorage as PagedStorage24 } from "@poe-platform/safe-fs/storage";
63463
64235
  async function editRetainedDocument(source, storage, options = {}) {
63464
64236
  if (options.maxPages !== void 0 && options.maxPages !== Infinity && (!Number.isSafeInteger(options.maxPages) || options.maxPages < 0)) throw new RangeError("Invalid page limit");
63465
64237
  if (options.maxRecursionDepth !== void 0 && options.maxRecursionDepth !== Infinity && (!Number.isSafeInteger(options.maxRecursionDepth) || options.maxRecursionDepth < 1)) throw new RangeError("Invalid edit depth");
63466
64238
  const signal = options.signal ?? new AbortController().signal;
63467
64239
  const store = new PdfMutableObjectStore(storage, { ...options, signal });
63468
- const pages = new PagedStorage22({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
64240
+ const pages = new PagedStorage24({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63469
64241
  const base = pages.allocate(0);
63470
64242
  let count = 0, document2;
63471
64243
  let closing;
@@ -63572,6 +64344,10 @@ async function editRetainedDocument(source, storage, options = {}) {
63572
64344
  }
63573
64345
  }
63574
64346
  } else if (options.removePageLabels) await removeRoot(["PageLabels"]);
64347
+ if (options.bookmarks) {
64348
+ await setRetainedBookmarks(store, storage, source.crossReference.rootRef, count, reference, options.bookmarks, signal, options.maxRecursionDepth);
64349
+ addedObjects = true;
64350
+ }
63575
64351
  if (options.generateAppearances && !options.removeAcroform) {
63576
64352
  await generateRetainedFormAppearances(document2, store, storage, signal);
63577
64353
  addedObjects = true;
@@ -63617,6 +64393,15 @@ async function editRetainedDocument(source, storage, options = {}) {
63617
64393
  await editRetainedAttachments(document2, store, storage, options.removeAttachments ?? [], options.attachments ?? [], signal);
63618
64394
  addedObjects = true;
63619
64395
  }
64396
+ if (options.appendAttachments) {
64397
+ if (options.attachmentPageIndex !== void 0 && (!Number.isSafeInteger(options.attachmentPageIndex) || options.attachmentPageIndex < 0 || options.attachmentPageIndex >= count)) throw new RangeError("Attachment page index out of bounds");
64398
+ if (addedObjects) {
64399
+ await document2.close();
64400
+ document2 = await PdfRetainedDocument.openStore(store, storage, { ...configured, ...infoRef ? { infoRef } : {} });
64401
+ }
64402
+ await appendRetainedAttachments(document2, store, storage, options.appendAttachments, { signal, ...options.attachmentPageIndex !== void 0 ? { pageIndex: options.attachmentPageIndex } : {} });
64403
+ addedObjects = true;
64404
+ }
63620
64405
  if (addedObjects || infoRef !== source.crossReference.infoRef) {
63621
64406
  await document2.close();
63622
64407
  document2 = await PdfRetainedDocument.openStore(store, storage, { ...configured, ...infoRef ? { infoRef } : {} });
@@ -63674,9 +64459,9 @@ async function* copyRetainedAttachments(document2, storage, options = {}) {
63674
64459
  }
63675
64460
 
63676
64461
  // packages/pdf-ast/src/cos/retained-object-order.ts
63677
- import { IntegerTable as IntegerTable14, PagedStorage as PagedStorage23 } from "@poe-platform/safe-fs/storage";
64462
+ import { IntegerTable as IntegerTable14, PagedStorage as PagedStorage25 } from "@poe-platform/safe-fs/storage";
63678
64463
  async function* retainedObjectOrder(document2, source, storage, signal) {
63679
- const backing = new PagedStorage23({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
64464
+ const backing = new PagedStorage25({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63680
64465
  const seen = new IntegerTable14(backing), streams = new IntegerTable14(backing);
63681
64466
  let failed = false, work = 0;
63682
64467
  async function candidate(number) {
@@ -63813,12 +64598,12 @@ async function* encryptRetainedPdfChunks(source, storage, options = {}) {
63813
64598
  }
63814
64599
 
63815
64600
  // packages/pdf-ast/src/cos/qpdf-json-values.ts
63816
- import { IntegerTable as IntegerTable15, PagedStorage as PagedStorage24 } from "@poe-platform/safe-fs/storage";
64601
+ import { IntegerTable as IntegerTable15, PagedStorage as PagedStorage26 } from "@poe-platform/safe-fs/storage";
63817
64602
  var QpdfJsonValues = class _QpdfJsonValues {
63818
64603
  constructor(tree, storage, signal) {
63819
64604
  this.tree = tree;
63820
64605
  this.signal = signal;
63821
- this.scratch = new PagedStorage24({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
64606
+ this.scratch = new PagedStorage26({ fs: storage.fs, cwd: storage.directory, env: {}, signal }, 4);
63822
64607
  this.first = new IntegerTable15(this.scratch, 64);
63823
64608
  this.next = new IntegerTable15(this.scratch, 64);
63824
64609
  }
@@ -64211,13 +64996,13 @@ var QpdfJsonValues = class _QpdfJsonValues {
64211
64996
  };
64212
64997
 
64213
64998
  // packages/pdf-ast/src/cos/qpdf-json-document.ts
64214
- import { IntegerTable as IntegerTable16, PagedStorage as PagedStorage25 } from "@poe-platform/safe-fs/storage";
64999
+ import { IntegerTable as IntegerTable16, PagedStorage as PagedStorage27 } from "@poe-platform/safe-fs/storage";
64215
65000
  var QpdfJsonDocument = class _QpdfJsonDocument {
64216
65001
  constructor(storage, options = {}) {
64217
65002
  this.storage = storage;
64218
65003
  this.signal = options.signal ? AbortSignal.any([options.signal, this.controller.signal]) : this.controller.signal;
64219
65004
  this.store = new PdfMutableObjectStore(storage, { signal: this.signal });
64220
- this.backing = new PagedStorage25(
65005
+ this.backing = new PagedStorage27(
64221
65006
  { fs: storage.fs, cwd: storage.directory, env: {}, signal: this.signal },
64222
65007
  4
64223
65008
  );
@@ -64286,7 +65071,7 @@ var QpdfJsonDocument = class _QpdfJsonDocument {
64286
65071
  env: {},
64287
65072
  signal: this.signal
64288
65073
  };
64289
- const tape = new PagedStorage25(context, 4), scratch = new PagedStorage25(context, 4);
65074
+ const tape = new PagedStorage27(context, 4), scratch = new PagedStorage27(context, 4);
64290
65075
  let values, failed = false, work = 0;
64291
65076
  const cooperate = async (units = 1) => {
64292
65077
  this.signal.throwIfAborted();
@@ -64703,6 +65488,8 @@ export {
64703
65488
  rc4Transform,
64704
65489
  readCMapCharacters,
64705
65490
  readCosXrefRevision,
65491
+ readPdfDictionaryEntries,
65492
+ readPdfDictionaryValue,
64706
65493
  readStoredItems,
64707
65494
  redactPageContentAst,
64708
65495
  renderDisplayListToBitmap,