@sync-in/server 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +38 -28
  3. package/environment/environment.dist.yaml +4 -0
  4. package/package.json +17 -17
  5. package/server/applications/files/utils/doc-textify/adapters/pdf.js +1 -1
  6. package/server/applications/files/utils/doc-textify/adapters/pdf.js.map +1 -1
  7. package/server/applications/files/utils/files.js +37 -24
  8. package/server/applications/files/utils/files.js.map +1 -1
  9. package/server/applications/notifications/i18n/index.js +5 -0
  10. package/server/applications/notifications/i18n/index.js.map +1 -1
  11. package/server/applications/notifications/i18n/nl.js +54 -0
  12. package/server/applications/notifications/i18n/nl.js.map +1 -0
  13. package/server/applications/sync/services/sync-clients-manager.service.js +1 -1
  14. package/server/applications/sync/services/sync-clients-manager.service.js.map +1 -1
  15. package/server/authentication/providers/oidc/auth-oidc.config.js +5 -0
  16. package/server/authentication/providers/oidc/auth-oidc.config.js.map +1 -1
  17. package/server/authentication/providers/oidc/auth-provider-oidc.service.js +10 -7
  18. package/server/authentication/providers/oidc/auth-provider-oidc.service.js.map +1 -1
  19. package/server/authentication/providers/oidc/auth-provider-oidc.service.spec.js +16 -0
  20. package/server/authentication/providers/oidc/auth-provider-oidc.service.spec.js.map +1 -1
  21. package/server/common/i18n.js +1 -0
  22. package/server/common/i18n.js.map +1 -1
  23. package/server/infrastructure/database/database.module.js +7 -0
  24. package/server/infrastructure/database/database.module.js.map +1 -1
  25. package/server/infrastructure/database/scripts/check-db.js +20 -0
  26. package/server/infrastructure/database/scripts/check-db.js.map +1 -0
  27. package/static/3rdpartylicenses.txt +391 -391
  28. package/static/assets/pdfjs/build/pdf.mjs +512 -417
  29. package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
  30. package/static/assets/pdfjs/build/pdf.sandbox.mjs +390 -4
  31. package/static/assets/pdfjs/build/pdf.sandbox.mjs.map +1 -1
  32. package/static/assets/pdfjs/build/pdf.worker.mjs +2378 -401
  33. package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
  34. package/static/assets/pdfjs/version +1 -1
  35. package/static/assets/pdfjs/web/debugger.mjs +6 -15
  36. package/static/assets/pdfjs/web/locale/be/viewer.ftl +78 -0
  37. package/static/assets/pdfjs/web/locale/cs/viewer.ftl +82 -0
  38. package/static/assets/pdfjs/web/locale/cy/viewer.ftl +90 -0
  39. package/static/assets/pdfjs/web/locale/de/viewer.ftl +75 -0
  40. package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +82 -0
  41. package/static/assets/pdfjs/web/locale/el/viewer.ftl +74 -0
  42. package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +74 -0
  43. package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +81 -0
  44. package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +14 -14
  45. package/static/assets/pdfjs/web/locale/eo/viewer.ftl +74 -0
  46. package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +74 -0
  47. package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +74 -0
  48. package/static/assets/pdfjs/web/locale/es-ES/viewer.ftl +74 -0
  49. package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +75 -0
  50. package/static/assets/pdfjs/web/locale/eu/viewer.ftl +74 -0
  51. package/static/assets/pdfjs/web/locale/fi/viewer.ftl +74 -0
  52. package/static/assets/pdfjs/web/locale/fr/viewer.ftl +81 -0
  53. package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +74 -0
  54. package/static/assets/pdfjs/web/locale/gn/viewer.ftl +77 -0
  55. package/static/assets/pdfjs/web/locale/he/viewer.ftl +81 -0
  56. package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +87 -0
  57. package/static/assets/pdfjs/web/locale/hu/viewer.ftl +74 -0
  58. package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +10 -10
  59. package/static/assets/pdfjs/web/locale/ia/viewer.ftl +75 -0
  60. package/static/assets/pdfjs/web/locale/it/viewer.ftl +81 -0
  61. package/static/assets/pdfjs/web/locale/ja/viewer.ftl +58 -0
  62. package/static/assets/pdfjs/web/locale/ka/viewer.ftl +74 -0
  63. package/static/assets/pdfjs/web/locale/kk/viewer.ftl +81 -0
  64. package/static/assets/pdfjs/web/locale/km/viewer.ftl +44 -0
  65. package/static/assets/pdfjs/web/locale/ko/viewer.ftl +65 -0
  66. package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +74 -0
  67. package/static/assets/pdfjs/web/locale/nl/viewer.ftl +81 -0
  68. package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +75 -0
  69. package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +74 -0
  70. package/static/assets/pdfjs/web/locale/pl/viewer.ftl +78 -0
  71. package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +74 -0
  72. package/static/assets/pdfjs/web/locale/ro/viewer.ftl +81 -3
  73. package/static/assets/pdfjs/web/locale/ru/viewer.ftl +85 -0
  74. package/static/assets/pdfjs/web/locale/sk/viewer.ftl +83 -1
  75. package/static/assets/pdfjs/web/locale/sl/viewer.ftl +82 -0
  76. package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +81 -0
  77. package/static/assets/pdfjs/web/locale/tg/viewer.ftl +74 -0
  78. package/static/assets/pdfjs/web/locale/th/viewer.ftl +58 -0
  79. package/static/assets/pdfjs/web/locale/tr/viewer.ftl +74 -0
  80. package/static/assets/pdfjs/web/locale/uk/viewer.ftl +144 -0
  81. package/static/assets/pdfjs/web/locale/vi/viewer.ftl +65 -0
  82. package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +61 -3
  83. package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +65 -0
  84. package/static/assets/pdfjs/web/viewer.css +292 -152
  85. package/static/assets/pdfjs/web/viewer.html +14 -21
  86. package/static/assets/pdfjs/web/viewer.mjs +782 -327
  87. package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
  88. package/static/assets/pdfjs/web/wasm/jbig2.wasm +0 -0
  89. package/static/{chunk-7WOPGQXB.js → chunk-25XD7GNL.js} +1 -1
  90. package/static/{chunk-E5WI5725.js → chunk-2W4Z5VTY.js} +1 -1
  91. package/static/chunk-2XNPCG4F.js +1 -0
  92. package/static/chunk-3B2RHO2H.js +1 -0
  93. package/static/{chunk-UMDRE4S7.js → chunk-3DNAFXGN.js} +1 -1
  94. package/static/{chunk-OANZITPM.js → chunk-3EPN4WD7.js} +1 -1
  95. package/static/chunk-4L2WBHB6.js +1 -0
  96. package/static/chunk-4RYZNAIZ.js +1 -0
  97. package/static/chunk-5C77PEFA.js +1 -0
  98. package/static/chunk-5JA3DZWQ.js +1 -0
  99. package/static/chunk-5MSTJGPE.js +1 -0
  100. package/static/{chunk-VSBFNFOM.js → chunk-5O7KTREI.js} +1 -1
  101. package/static/chunk-6KORLSUZ.js +1 -0
  102. package/static/chunk-6LIHQVPW.js +2 -0
  103. package/static/{chunk-2CKLZ3FM.js → chunk-72BXGTUG.js} +1 -1
  104. package/static/chunk-7423QJQN.js +1 -0
  105. package/static/chunk-77HB4DE6.js +1 -0
  106. package/static/{chunk-RWAAC3A4.js → chunk-7PVTMTWH.js} +1 -1
  107. package/static/{chunk-IWWBV6EM.js → chunk-7UIOW5AD.js} +1 -1
  108. package/static/chunk-7YMONFZZ.js +1 -0
  109. package/static/chunk-AUPNSQGJ.js +1 -0
  110. package/static/chunk-AYF6ZI6L.js +5 -0
  111. package/static/chunk-BEESW4BF.js +1 -0
  112. package/static/{chunk-2R6IBBPZ.js → chunk-BI3VI6XG.js} +1 -1
  113. package/static/chunk-BMGKB3JK.js +4 -0
  114. package/static/chunk-CFXAKPPB.js +563 -0
  115. package/static/chunk-CGYZG6CB.js +2 -0
  116. package/static/{chunk-K25E7YGG.js → chunk-CHAYERHQ.js} +1 -1
  117. package/static/chunk-CLNKPQMZ.js +1 -0
  118. package/static/{chunk-ISV3BO6R.js → chunk-CVLSRA2W.js} +1 -1
  119. package/static/chunk-D373HBMN.js +1 -0
  120. package/static/{chunk-MTRXBVWZ.js → chunk-D43PHZEY.js} +1 -1
  121. package/static/chunk-D44RAVFK.js +1 -0
  122. package/static/chunk-DFVVEGWC.js +1 -0
  123. package/static/chunk-E43LXI27.js +1 -0
  124. package/static/{chunk-GQFMWVFD.js → chunk-E5M4ZDID.js} +1 -1
  125. package/static/chunk-F7JS3YWP.js +2 -0
  126. package/static/chunk-FRWEEOOM.js +1 -0
  127. package/static/chunk-HIZGSP7R.js +1 -0
  128. package/static/chunk-HX6ZWXQD.js +1 -0
  129. package/static/chunk-HZ6LLXLE.js +1 -0
  130. package/static/{chunk-RLL634K4.js → chunk-IFHFPV5W.js} +1 -1
  131. package/static/{chunk-KJD3KFF3.js → chunk-JICKUOQ6.js} +1 -1
  132. package/static/chunk-KY2BW2LP.js +1 -0
  133. package/static/{chunk-CWYHOPOP.js → chunk-KYA3HPDX.js} +1 -1
  134. package/static/{chunk-RWCNTCU5.js → chunk-KYLATNX5.js} +1 -1
  135. package/static/chunk-LCZNSV4Z.js +1 -0
  136. package/static/{chunk-GVNTC564.js → chunk-MA6DYTMQ.js} +1 -1
  137. package/static/{chunk-KZS7CTNR.js → chunk-MXH5XYBD.js} +1 -1
  138. package/static/{chunk-NMTBMHUL.js → chunk-MXIJGSDQ.js} +1 -1
  139. package/static/{chunk-RS2OFKWP.js → chunk-NE75E3GD.js} +1 -1
  140. package/static/{chunk-MZQK6LNV.js → chunk-NJKIHMOH.js} +1 -1
  141. package/static/chunk-NMDGST45.js +1 -0
  142. package/static/{chunk-CU76ATCF.js → chunk-OF7P4LTI.js} +1 -1
  143. package/static/chunk-OK5K5CYJ.js +13 -0
  144. package/static/chunk-OZ6LXMUH.js +1 -0
  145. package/static/chunk-PFY6YUPS.js +2 -0
  146. package/static/chunk-PQ2YFCVM.js +1 -0
  147. package/static/{chunk-Y4AUYQTG.js → chunk-QPX34S6P.js} +4 -4
  148. package/static/{chunk-27ATUHBH.js → chunk-QQO7S2VY.js} +1 -1
  149. package/static/chunk-RANZZPRG.js +1 -0
  150. package/static/{chunk-WN4WXCVK.js → chunk-RNQB2QJB.js} +1 -1
  151. package/static/{chunk-Q3EGCMF5.js → chunk-S7QYAKG5.js} +1 -1
  152. package/static/chunk-SCEWOW5C.js +2 -0
  153. package/static/chunk-SQ2KIOJ7.js +1 -0
  154. package/static/{chunk-QVRVFYJH.js → chunk-SW5GCGOI.js} +1 -1
  155. package/static/chunk-SWCYWB2T.js +1 -0
  156. package/static/{chunk-4FIGEBNL.js → chunk-SWZ3L2LK.js} +1 -1
  157. package/static/{chunk-TWCGKSYE.js → chunk-TDK62XEQ.js} +1 -1
  158. package/static/chunk-TH4L5H6P.js +1 -0
  159. package/static/chunk-U3ZGYOLA.js +1 -0
  160. package/static/chunk-U6V4Y234.js +1 -0
  161. package/static/chunk-U7KNV64D.js +2 -0
  162. package/static/chunk-UC66HJV4.js +1 -0
  163. package/static/{chunk-7GWW6MJO.js → chunk-V4HAIERK.js} +1 -1
  164. package/static/chunk-V55LDRV7.js +1 -0
  165. package/static/{chunk-5CZOSAMZ.js → chunk-WF6D7CQ4.js} +1 -1
  166. package/static/chunk-WJPVHM7T.js +1 -0
  167. package/static/chunk-WM4XBDC2.js +1 -0
  168. package/static/chunk-X2EKQYMZ.js +1 -0
  169. package/static/{chunk-L5IHUVXL.js → chunk-XEDABMM5.js} +1 -1
  170. package/static/{chunk-OGE4SAHU.js → chunk-Y3YKVK3K.js} +1 -1
  171. package/static/{chunk-QIGUDEZF.js → chunk-YEOAMYRK.js} +1 -1
  172. package/static/{chunk-A4UGPSWX.js → chunk-ZLTL7I7D.js} +1 -1
  173. package/static/chunk-ZYNBYM7I.js +3 -0
  174. package/static/index.html +2 -2
  175. package/static/main-KFUSRCP5.js +5 -0
  176. package/static/media/inter-cyrillic-ext-wght-normal-IYF56FF6.woff2 +0 -0
  177. package/static/media/inter-cyrillic-wght-normal-JEOLYBOO.woff2 +0 -0
  178. package/static/media/inter-greek-ext-wght-normal-EOVOK2B5.woff2 +0 -0
  179. package/static/media/inter-greek-wght-normal-IRE366VL.woff2 +0 -0
  180. package/static/media/inter-latin-ext-wght-normal-HA22NDSG.woff2 +0 -0
  181. package/static/media/inter-latin-wght-normal-NRMW37G5.woff2 +0 -0
  182. package/static/media/inter-vietnamese-wght-normal-CE5GGD3W.woff2 +0 -0
  183. package/static/styles-66AEF62D.css +1 -0
  184. package/static/chunk-22TZP6HW.js +0 -1
  185. package/static/chunk-2QZPX7LO.js +0 -1
  186. package/static/chunk-4P3JABAP.js +0 -13
  187. package/static/chunk-677WUBCT.js +0 -1
  188. package/static/chunk-74CAHBFM.js +0 -1
  189. package/static/chunk-AHO37FKW.js +0 -1
  190. package/static/chunk-AQCXMKP3.js +0 -1
  191. package/static/chunk-B6PDYCRO.js +0 -3
  192. package/static/chunk-FC5HTKVM.js +0 -1
  193. package/static/chunk-FOSM7EYI.js +0 -1
  194. package/static/chunk-GAZO25PI.js +0 -1
  195. package/static/chunk-GB7ABR5N.js +0 -1
  196. package/static/chunk-GEHFKZQ5.js +0 -2
  197. package/static/chunk-HGL3NYP2.js +0 -2
  198. package/static/chunk-HLIWPWRA.js +0 -1
  199. package/static/chunk-HNYB3M4S.js +0 -1
  200. package/static/chunk-HUXAUQMN.js +0 -1
  201. package/static/chunk-I2XA6PPK.js +0 -1
  202. package/static/chunk-JV3AGU5B.js +0 -1
  203. package/static/chunk-K46PUTZB.js +0 -1
  204. package/static/chunk-KERFLJ56.js +0 -1
  205. package/static/chunk-KPKSI23S.js +0 -1
  206. package/static/chunk-L7RRX2M3.js +0 -1
  207. package/static/chunk-LGWJ2WKU.js +0 -1
  208. package/static/chunk-LUSVISM6.js +0 -1
  209. package/static/chunk-MLC7JK2H.js +0 -2
  210. package/static/chunk-MOHNYW2A.js +0 -1
  211. package/static/chunk-NCDUOVMW.js +0 -1
  212. package/static/chunk-NGUAJIGI.js +0 -1
  213. package/static/chunk-NIPP6JDI.js +0 -1
  214. package/static/chunk-O4XXMZFX.js +0 -4
  215. package/static/chunk-OI3ME22C.js +0 -1
  216. package/static/chunk-QF2NSHZA.js +0 -1
  217. package/static/chunk-QJVC3SRJ.js +0 -562
  218. package/static/chunk-QKN6LAAA.js +0 -1
  219. package/static/chunk-QRFESU5O.js +0 -2
  220. package/static/chunk-RFJIPIOK.js +0 -2
  221. package/static/chunk-S5Y64DDS.js +0 -1
  222. package/static/chunk-SLG5KDU6.js +0 -1
  223. package/static/chunk-TJ4CVFEL.js +0 -1
  224. package/static/chunk-VRIOLRYR.js +0 -5
  225. package/static/chunk-VS4O2XDP.js +0 -1
  226. package/static/chunk-WX7RXW7K.js +0 -1
  227. package/static/chunk-XC4POKR3.js +0 -2
  228. package/static/chunk-Y67J3BOL.js +0 -1
  229. package/static/chunk-YMIXHRJQ.js +0 -1
  230. package/static/chunk-ZUNKFAKP.js +0 -1
  231. package/static/main-QN4UCOC5.js +0 -5
  232. package/static/styles-46GLIE7Y.css +0 -1
@@ -21,8 +21,8 @@
21
21
  */
22
22
 
23
23
  /**
24
- * pdfjsVersion = 5.4.624
25
- * pdfjsBuild = 384c6208b
24
+ * pdfjsVersion = 5.5.207
25
+ * pdfjsBuild = 527964698
26
26
  */
27
27
  /******/ // The require scope
28
28
  /******/ var __webpack_require__ = {};
@@ -70,7 +70,7 @@ const {
70
70
  findContrastColor,
71
71
  getDocument,
72
72
  getFilenameFromUrl,
73
- getPdfFilenameFromUrl: pdfjs_getPdfFilenameFromUrl,
73
+ getPdfFilenameFromUrl,
74
74
  getRGB,
75
75
  getUuid,
76
76
  getXfaPageViewport,
@@ -80,12 +80,14 @@ const {
80
80
  isDataScheme,
81
81
  isPdfFile,
82
82
  isValidExplicitDest,
83
+ makeArr,
84
+ makeMap,
85
+ makeObj,
83
86
  MathClamp,
84
87
  noContextMenu,
85
88
  normalizeUnicode,
86
89
  OPS,
87
90
  OutputScale,
88
- PagesMapper,
89
91
  PasswordResponses,
90
92
  PDFDataRangeTransport,
91
93
  PDFDateString,
@@ -120,12 +122,6 @@ const UNKNOWN_SCALE = 0;
120
122
  const MAX_AUTO_SCALE = 1.25;
121
123
  const SCROLLBAR_PADDING = 40;
122
124
  const VERTICAL_PADDING = 5;
123
- const RenderingStates = {
124
- INITIAL: 0,
125
- RUNNING: 1,
126
- PAUSED: 2,
127
- FINISHED: 3
128
- };
129
125
  const PresentationModeState = {
130
126
  UNKNOWN: 0,
131
127
  NORMAL: 1,
@@ -1090,7 +1086,7 @@ class PDFLinkService {
1090
1086
  this.pdfHistory = pdfHistory;
1091
1087
  }
1092
1088
  get pagesCount() {
1093
- return this.pdfDocument ? this.pdfDocument.numPages : 0;
1089
+ return this.pdfDocument?.pagesMapper.pagesNumber || 0;
1094
1090
  }
1095
1091
  get page() {
1096
1092
  return this.pdfDocument ? this.pdfViewer.currentPageNumber : 1;
@@ -3121,12 +3117,13 @@ class genericl10n_GenericL10n extends L10n {
3121
3117
  yield this.#createBundleFallback(lang);
3122
3118
  }
3123
3119
  static async #createBundleFallback(lang) {
3124
- const text = "pdfjs-previous-button =\n .title = Previous Page\npdfjs-previous-button-label = Previous\npdfjs-next-button =\n .title = Next Page\npdfjs-next-button-label = Next\npdfjs-page-input =\n .title = Page\npdfjs-of-pages = of { $pagesCount }\npdfjs-page-of-pages = ({ $pageNumber } of { $pagesCount })\npdfjs-zoom-out-button =\n .title = Zoom Out\npdfjs-zoom-out-button-label = Zoom Out\npdfjs-zoom-in-button =\n .title = Zoom In\npdfjs-zoom-in-button-label = Zoom In\npdfjs-zoom-select =\n .title = Zoom\npdfjs-presentation-mode-button =\n .title = Switch to Presentation Mode\npdfjs-presentation-mode-button-label = Presentation Mode\npdfjs-open-file-button =\n .title = Open File\npdfjs-open-file-button-label = Open\npdfjs-print-button =\n .title = Print\npdfjs-print-button-label = Print\npdfjs-save-button =\n .title = Save\npdfjs-save-button-label = Save\npdfjs-download-button =\n .title = Download\npdfjs-download-button-label = Download\npdfjs-bookmark-button =\n .title = Current Page (View URL from Current Page)\npdfjs-bookmark-button-label = Current Page\npdfjs-tools-button =\n .title = Tools\npdfjs-tools-button-label = Tools\npdfjs-first-page-button =\n .title = Go to First Page\npdfjs-first-page-button-label = Go to First Page\npdfjs-last-page-button =\n .title = Go to Last Page\npdfjs-last-page-button-label = Go to Last Page\npdfjs-page-rotate-cw-button =\n .title = Rotate Clockwise\npdfjs-page-rotate-cw-button-label = Rotate Clockwise\npdfjs-page-rotate-ccw-button =\n .title = Rotate Counterclockwise\npdfjs-page-rotate-ccw-button-label = Rotate Counterclockwise\npdfjs-cursor-text-select-tool-button =\n .title = Enable Text Selection Tool\npdfjs-cursor-text-select-tool-button-label = Text Selection Tool\npdfjs-cursor-hand-tool-button =\n .title = Enable Hand Tool\npdfjs-cursor-hand-tool-button-label = Hand Tool\npdfjs-scroll-page-button =\n .title = Use Page Scrolling\npdfjs-scroll-page-button-label = Page Scrolling\npdfjs-scroll-vertical-button =\n .title = Use Vertical Scrolling\npdfjs-scroll-vertical-button-label = Vertical Scrolling\npdfjs-scroll-horizontal-button =\n .title = Use Horizontal Scrolling\npdfjs-scroll-horizontal-button-label = Horizontal Scrolling\npdfjs-scroll-wrapped-button =\n .title = Use Wrapped Scrolling\npdfjs-scroll-wrapped-button-label = Wrapped Scrolling\npdfjs-spread-none-button =\n .title = Do not join page spreads\npdfjs-spread-none-button-label = No Spreads\npdfjs-spread-odd-button =\n .title = Join page spreads starting with odd-numbered pages\npdfjs-spread-odd-button-label = Odd Spreads\npdfjs-spread-even-button =\n .title = Join page spreads starting with even-numbered pages\npdfjs-spread-even-button-label = Even Spreads\npdfjs-document-properties-button =\n .title = Document Properties\u2026\npdfjs-document-properties-button-label = Document Properties\u2026\npdfjs-document-properties-file-name = File name:\npdfjs-document-properties-file-size = File size:\npdfjs-document-properties-size-kb = { NUMBER($kb, maximumSignificantDigits: 3) } KB ({ $b } bytes)\npdfjs-document-properties-size-mb = { NUMBER($mb, maximumSignificantDigits: 3) } MB ({ $b } bytes)\npdfjs-document-properties-title = Title:\npdfjs-document-properties-author = Author:\npdfjs-document-properties-subject = Subject:\npdfjs-document-properties-keywords = Keywords:\npdfjs-document-properties-creation-date = Creation Date:\npdfjs-document-properties-modification-date = Modification Date:\npdfjs-document-properties-date-time-string = { DATETIME($dateObj, dateStyle: \"short\", timeStyle: \"medium\") }\npdfjs-document-properties-creator = Creator:\npdfjs-document-properties-producer = PDF Producer:\npdfjs-document-properties-version = PDF Version:\npdfjs-document-properties-page-count = Page Count:\npdfjs-document-properties-page-size = Page Size:\npdfjs-document-properties-page-size-unit-inches = in\npdfjs-document-properties-page-size-unit-millimeters = mm\npdfjs-document-properties-page-size-orientation-portrait = portrait\npdfjs-document-properties-page-size-orientation-landscape = landscape\npdfjs-document-properties-page-size-name-a-three = A3\npdfjs-document-properties-page-size-name-a-four = A4\npdfjs-document-properties-page-size-name-letter = Letter\npdfjs-document-properties-page-size-name-legal = Legal\npdfjs-document-properties-page-size-dimension-string = { $width } \xD7 { $height } { $unit } ({ $orientation })\npdfjs-document-properties-page-size-dimension-name-string = { $width } \xD7 { $height } { $unit } ({ $name }, { $orientation })\npdfjs-document-properties-linearized = Fast Web View:\npdfjs-document-properties-linearized-yes = Yes\npdfjs-document-properties-linearized-no = No\npdfjs-document-properties-close-button = Close\npdfjs-print-progress-message = Preparing document for printing\u2026\npdfjs-print-progress-percent = { $progress }%\npdfjs-print-progress-close-button = Cancel\npdfjs-printing-not-supported = Warning: Printing is not fully supported by this browser.\npdfjs-printing-not-ready = Warning: The PDF is not fully loaded for printing.\npdfjs-current-outline-item-button =\n .title = Find Current Outline Item\npdfjs-current-outline-item-button-label = Current Outline Item\npdfjs-findbar-button =\n .title = Find in Document\npdfjs-findbar-button-label = Find\npdfjs-additional-layers = Additional Layers\npdfjs-thumb-page-title =\n .title = Page { $page }\npdfjs-thumb-page-canvas =\n .aria-label = Thumbnail of Page { $page }\npdfjs-find-input =\n .title = Find\n .placeholder = Find in document\u2026\npdfjs-find-previous-button =\n .title = Find the previous occurrence of the phrase\npdfjs-find-previous-button-label = Previous\npdfjs-find-next-button =\n .title = Find the next occurrence of the phrase\npdfjs-find-next-button-label = Next\npdfjs-find-highlight-checkbox = Highlight All\npdfjs-find-match-case-checkbox-label = Match Case\npdfjs-find-match-diacritics-checkbox-label = Match Diacritics\npdfjs-find-entire-word-checkbox-label = Whole Words\npdfjs-find-reached-top = Reached top of document, continued from bottom\npdfjs-find-reached-bottom = Reached end of document, continued from top\npdfjs-find-match-count =\n { $total ->\n [one] { $current } of { $total } match\n *[other] { $current } of { $total } matches\n }\npdfjs-find-match-count-limit =\n { $limit ->\n [one] More than { $limit } match\n *[other] More than { $limit } matches\n }\npdfjs-find-not-found = Phrase not found\npdfjs-page-scale-width = Page Width\npdfjs-page-scale-fit = Page Fit\npdfjs-page-scale-auto = Automatic Zoom\npdfjs-page-scale-actual = Actual Size\npdfjs-page-scale-percent = { $scale }%\npdfjs-page-landmark =\n .aria-label = Page { $page }\npdfjs-loading-error = An error occurred while loading the PDF.\npdfjs-invalid-file-error = Invalid or corrupted PDF file.\npdfjs-missing-file-error = Missing PDF file.\npdfjs-unexpected-response-error = Unexpected server response.\npdfjs-rendering-error = An error occurred while rendering the page.\npdfjs-annotation-date-time-string = { DATETIME($dateObj, dateStyle: \"short\", timeStyle: \"medium\") }\npdfjs-text-annotation-type =\n .alt = [{ $type } Annotation]\npdfjs-password-label = Enter the password to open this PDF file.\npdfjs-password-invalid = Invalid password. Please try again.\npdfjs-password-ok-button = OK\npdfjs-password-cancel-button = Cancel\npdfjs-web-fonts-disabled = Web fonts are disabled: unable to use embedded PDF fonts.\npdfjs-editor-free-text-button =\n .title = Text\npdfjs-editor-color-picker-free-text-input =\n .title = Change text color\npdfjs-editor-free-text-button-label = Text\npdfjs-editor-ink-button =\n .title = Draw\npdfjs-editor-color-picker-ink-input =\n .title = Change drawing color\npdfjs-editor-ink-button-label = Draw\npdfjs-editor-stamp-button =\n .title = Add or edit images\npdfjs-editor-stamp-button-label = Add or edit images\npdfjs-editor-highlight-button =\n .title = Highlight\npdfjs-editor-highlight-button-label = Highlight\npdfjs-highlight-floating-button1 =\n .title = Highlight\n .aria-label = Highlight\npdfjs-highlight-floating-button-label = Highlight\npdfjs-comment-floating-button =\n .title = Comment\n .aria-label = Comment\npdfjs-comment-floating-button-label = Comment\npdfjs-editor-comment-button =\n .title = Comment\n .aria-label = Comment\npdfjs-editor-comment-button-label = Comment\npdfjs-editor-signature-button =\n .title = Add signature\npdfjs-editor-signature-button-label = Add signature\npdfjs-editor-highlight-editor =\n .aria-label = Highlight editor\npdfjs-editor-ink-editor =\n .aria-label = Drawing editor\npdfjs-editor-signature-editor1 =\n .aria-description = Signature editor: { $description }\npdfjs-editor-stamp-editor =\n .aria-label = Image editor\npdfjs-editor-remove-ink-button =\n .title = Remove drawing\npdfjs-editor-remove-freetext-button =\n .title = Remove text\npdfjs-editor-remove-stamp-button =\n .title = Remove image\npdfjs-editor-remove-highlight-button =\n .title = Remove highlight\npdfjs-editor-remove-signature-button =\n .title = Remove signature\npdfjs-editor-free-text-color-input = Color\npdfjs-editor-free-text-size-input = Size\npdfjs-editor-ink-color-input = Color\npdfjs-editor-ink-thickness-input = Thickness\npdfjs-editor-ink-opacity-input = Opacity\npdfjs-editor-stamp-add-image-button =\n .title = Add image\npdfjs-editor-stamp-add-image-button-label = Add image\npdfjs-editor-free-highlight-thickness-input = Thickness\npdfjs-editor-free-highlight-thickness-title =\n .title = Change thickness when highlighting items other than text\npdfjs-editor-add-signature-container =\n .aria-label = Signature controls and saved signatures\npdfjs-editor-signature-add-signature-button =\n .title = Add new signature\npdfjs-editor-signature-add-signature-button-label = Add new signature\npdfjs-editor-add-saved-signature-button =\n .title = Saved signature: { $description }\npdfjs-free-text2 =\n .aria-label = Text Editor\n .default-content = Start typing\u2026\npdfjs-editor-comments-sidebar-title =\n { $count ->\n [one] Comment\n *[other] Comments\n }\npdfjs-editor-comments-sidebar-close-button =\n .title = Close the sidebar\n .aria-label = Close the sidebar\npdfjs-editor-comments-sidebar-close-button-label = Close the sidebar\npdfjs-editor-comments-sidebar-no-comments1 = See something noteworthy? Highlight it and leave a comment.\npdfjs-editor-comments-sidebar-no-comments-link = Learn more\npdfjs-editor-alt-text-button =\n .aria-label = Alt text\npdfjs-editor-alt-text-button-label = Alt text\npdfjs-editor-alt-text-edit-button =\n .aria-label = Edit alt text\npdfjs-editor-alt-text-dialog-label = Choose an option\npdfjs-editor-alt-text-dialog-description = Alt text (alternative text) helps when people can\u2019t see the image or when it doesn\u2019t load.\npdfjs-editor-alt-text-add-description-label = Add a description\npdfjs-editor-alt-text-add-description-description = Aim for 1-2 sentences that describe the subject, setting, or actions.\npdfjs-editor-alt-text-mark-decorative-label = Mark as decorative\npdfjs-editor-alt-text-mark-decorative-description = This is used for ornamental images, like borders or watermarks.\npdfjs-editor-alt-text-cancel-button = Cancel\npdfjs-editor-alt-text-save-button = Save\npdfjs-editor-alt-text-decorative-tooltip = Marked as decorative\npdfjs-editor-alt-text-textarea =\n .placeholder = For example, \u201CA young man sits down at a table to eat a meal\u201D\npdfjs-editor-resizer-top-left =\n .aria-label = Top left corner \u2014 resize\npdfjs-editor-resizer-top-middle =\n .aria-label = Top middle \u2014 resize\npdfjs-editor-resizer-top-right =\n .aria-label = Top right corner \u2014 resize\npdfjs-editor-resizer-middle-right =\n .aria-label = Middle right \u2014 resize\npdfjs-editor-resizer-bottom-right =\n .aria-label = Bottom right corner \u2014 resize\npdfjs-editor-resizer-bottom-middle =\n .aria-label = Bottom middle \u2014 resize\npdfjs-editor-resizer-bottom-left =\n .aria-label = Bottom left corner \u2014 resize\npdfjs-editor-resizer-middle-left =\n .aria-label = Middle left \u2014 resize\npdfjs-editor-highlight-colorpicker-label = Highlight color\npdfjs-editor-colorpicker-button =\n .title = Change color\npdfjs-editor-colorpicker-dropdown =\n .aria-label = Color choices\npdfjs-editor-colorpicker-yellow =\n .title = Yellow\npdfjs-editor-colorpicker-green =\n .title = Green\npdfjs-editor-colorpicker-blue =\n .title = Blue\npdfjs-editor-colorpicker-pink =\n .title = Pink\npdfjs-editor-colorpicker-red =\n .title = Red\npdfjs-editor-highlight-show-all-button-label = Show all\npdfjs-editor-highlight-show-all-button =\n .title = Show all\npdfjs-editor-new-alt-text-dialog-edit-label = Edit alt text (image description)\npdfjs-editor-new-alt-text-dialog-add-label = Add alt text (image description)\npdfjs-editor-new-alt-text-textarea =\n .placeholder = Write your description here\u2026\npdfjs-editor-new-alt-text-description = Short description for people who can\u2019t see the image or when the image doesn\u2019t load.\npdfjs-editor-new-alt-text-disclaimer1 = This alt text was created automatically and may be inaccurate.\npdfjs-editor-new-alt-text-disclaimer-learn-more-url = Learn more\npdfjs-editor-new-alt-text-create-automatically-button-label = Create alt text automatically\npdfjs-editor-new-alt-text-not-now-button = Not now\npdfjs-editor-new-alt-text-error-title = Couldn\u2019t create alt text automatically\npdfjs-editor-new-alt-text-error-description = Please write your own alt text or try again later.\npdfjs-editor-new-alt-text-error-close-button = Close\npdfjs-editor-new-alt-text-ai-model-downloading-progress = Downloading alt text AI model ({ $downloadedSize } of { $totalSize } MB)\n .aria-valuetext = Downloading alt text AI model ({ $downloadedSize } of { $totalSize } MB)\npdfjs-editor-new-alt-text-added-button =\n .aria-label = Alt text added\npdfjs-editor-new-alt-text-added-button-label = Alt text added\npdfjs-editor-new-alt-text-missing-button =\n .aria-label = Missing alt text\npdfjs-editor-new-alt-text-missing-button-label = Missing alt text\npdfjs-editor-new-alt-text-to-review-button =\n .aria-label = Review alt text\npdfjs-editor-new-alt-text-to-review-button-label = Review alt text\npdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer = Created automatically: { $generatedAltText }\npdfjs-image-alt-text-settings-button =\n .title = Image alt text settings\npdfjs-image-alt-text-settings-button-label = Image alt text settings\npdfjs-editor-alt-text-settings-dialog-label = Image alt text settings\npdfjs-editor-alt-text-settings-automatic-title = Automatic alt text\npdfjs-editor-alt-text-settings-create-model-button-label = Create alt text automatically\npdfjs-editor-alt-text-settings-create-model-description = Suggests descriptions to help people who can\u2019t see the image or when the image doesn\u2019t load.\npdfjs-editor-alt-text-settings-download-model-label = Alt text AI model ({ $totalSize } MB)\npdfjs-editor-alt-text-settings-ai-model-description = Runs locally on your device so your data stays private. Required for automatic alt text.\npdfjs-editor-alt-text-settings-delete-model-button = Delete\npdfjs-editor-alt-text-settings-download-model-button = Download\npdfjs-editor-alt-text-settings-downloading-model-button = Downloading\u2026\npdfjs-editor-alt-text-settings-editor-title = Alt text editor\npdfjs-editor-alt-text-settings-show-dialog-button-label = Show alt text editor right away when adding an image\npdfjs-editor-alt-text-settings-show-dialog-description = Helps you make sure all your images have alt text.\npdfjs-editor-alt-text-settings-close-button = Close\npdfjs-editor-highlight-added-alert = Highlight added\npdfjs-editor-freetext-added-alert = Text added\npdfjs-editor-ink-added-alert = Drawing added\npdfjs-editor-stamp-added-alert = Image added\npdfjs-editor-signature-added-alert = Signature added\npdfjs-editor-undo-bar-message-highlight = Highlight removed\npdfjs-editor-undo-bar-message-freetext = Text removed\npdfjs-editor-undo-bar-message-ink = Drawing removed\npdfjs-editor-undo-bar-message-stamp = Image removed\npdfjs-editor-undo-bar-message-signature = Signature removed\npdfjs-editor-undo-bar-message-comment = Comment removed\npdfjs-editor-undo-bar-message-multiple =\n { $count ->\n [one] { $count } annotation removed\n *[other] { $count } annotations removed\n }\npdfjs-editor-undo-bar-undo-button =\n .title = Undo\npdfjs-editor-undo-bar-undo-button-label = Undo\npdfjs-editor-undo-bar-close-button =\n .title = Close\npdfjs-editor-undo-bar-close-button-label = Close\npdfjs-editor-add-signature-dialog-label = This modal allows the user to create a signature to add to a PDF document. The user can edit the name (which also serves as the alt text), and optionally save the signature for repeated use.\npdfjs-editor-add-signature-dialog-title = Add a signature\npdfjs-editor-add-signature-type-button = Type\n .title = Type\npdfjs-editor-add-signature-draw-button = Draw\n .title = Draw\npdfjs-editor-add-signature-image-button = Image\n .title = Image\npdfjs-editor-add-signature-type-input =\n .aria-label = Type your signature\n .placeholder = Type your signature\npdfjs-editor-add-signature-draw-placeholder = Draw your signature\npdfjs-editor-add-signature-draw-thickness-range-label = Thickness\npdfjs-editor-add-signature-draw-thickness-range =\n .title = Drawing thickness: { $thickness }\npdfjs-editor-add-signature-image-placeholder = Drag a file here to upload\npdfjs-editor-add-signature-image-browse-link =\n { PLATFORM() ->\n [macos] Or choose image files\n *[other] Or browse image files\n }\npdfjs-editor-add-signature-description-label = Description (alt text)\npdfjs-editor-add-signature-description-input =\n .title = Description (alt text)\npdfjs-editor-add-signature-description-default-when-drawing = Signature\npdfjs-editor-add-signature-clear-button-label = Clear signature\npdfjs-editor-add-signature-clear-button =\n .title = Clear signature\npdfjs-editor-add-signature-save-checkbox = Save signature\npdfjs-editor-add-signature-save-warning-message = You\u2019ve reached the limit of 5 saved signatures. Remove one to save more.\npdfjs-editor-add-signature-image-upload-error-title = Couldn\u2019t upload image\npdfjs-editor-add-signature-image-upload-error-description = Check your network connection or try another image.\npdfjs-editor-add-signature-image-no-data-error-title = Can\u2019t convert this image into a signature\npdfjs-editor-add-signature-image-no-data-error-description = Please try uploading a different image.\npdfjs-editor-add-signature-error-close-button = Close\npdfjs-editor-add-signature-cancel-button = Cancel\npdfjs-editor-add-signature-add-button = Add\npdfjs-editor-delete-signature-button1 =\n .title = Remove saved signature\npdfjs-editor-delete-signature-button-label1 = Remove saved signature\npdfjs-editor-add-signature-edit-button-label = Edit description\npdfjs-editor-edit-signature-dialog-title = Edit description\npdfjs-editor-edit-signature-update-button = Update\npdfjs-show-comment-button =\n .title = Show comment\npdfjs-editor-edit-comment-popup-button-label = Edit comment\npdfjs-editor-edit-comment-popup-button =\n .title = Edit comment\npdfjs-editor-delete-comment-popup-button-label = Remove comment\npdfjs-editor-delete-comment-popup-button =\n .title = Remove comment\npdfjs-editor-edit-comment-dialog-title-when-editing = Edit comment\npdfjs-editor-edit-comment-dialog-save-button-when-editing = Update\npdfjs-editor-edit-comment-dialog-title-when-adding = Add comment\npdfjs-editor-edit-comment-dialog-save-button-when-adding = Add\npdfjs-editor-edit-comment-dialog-text-input =\n .placeholder = Start typing\u2026\npdfjs-editor-edit-comment-dialog-cancel-button = Cancel\npdfjs-editor-add-comment-button =\n .title = Add comment\npdfjs-toggle-views-manager-button =\n .title = Toggle Sidebar\npdfjs-toggle-views-manager-notification-button =\n .title = Toggle Sidebar (document contains thumbnails/outline/attachments/layers)\npdfjs-toggle-views-manager-button-label = Toggle Sidebar\npdfjs-views-manager-sidebar =\n .aria-label = Sidebar\npdfjs-views-manager-view-selector-button =\n .title = Views\npdfjs-views-manager-view-selector-button-label = Views\npdfjs-views-manager-pages-title = Pages\npdfjs-views-manager-outlines-title = Document outline\npdfjs-views-manager-attachments-title = Attachments\npdfjs-views-manager-layers-title = Layers\npdfjs-views-manager-pages-option-label = Pages\npdfjs-views-manager-outlines-option-label = Document outline\npdfjs-views-manager-attachments-option-label = Attachments\npdfjs-views-manager-layers-option-label = Layers\npdfjs-views-manager-add-file-button =\n .title = Add file\npdfjs-views-manager-add-file-button-label = Add file\npdfjs-views-manager-pages-status-action-label =\n { $count ->\n [one] { $count } selected\n *[other] { $count } selected\n }\npdfjs-views-manager-pages-status-none-action-label = Select pages\npdfjs-views-manager-pages-status-action-button-label = Manage\npdfjs-views-manager-pages-status-copy-button-label = Copy\npdfjs-views-manager-pages-status-cut-button-label = Cut\npdfjs-views-manager-pages-status-delete-button-label = Delete\npdfjs-views-manager-pages-status-save-as-button-label = Save as\u2026\npdfjs-views-manager-status-undo-cut-label =\n { $count ->\n [one] 1 page cut\n *[other] { $count } pages cut\n }\npdfjs-views-manager-pages-status-undo-copy-label =\n { $count ->\n [one] 1 page copied\n *[other] { $count } pages copied\n }\npdfjs-views-manager-pages-status-undo-delete-label =\n { $count ->\n [one] 1 page deleted\n *[other] { $count } pages deleted\n }\npdfjs-views-manager-pages-status-waiting-ready-label = Getting your file ready\u2026\npdfjs-views-manager-pages-status-waiting-uploading-label = Uploading file\u2026\npdfjs-views-manager-status-warning-cut-label = Couldn\u2019t cut. Refresh page and try again.\npdfjs-views-manager-status-warning-copy-label = Couldn\u2019t copy. Refresh page and try again.\npdfjs-views-manager-status-warning-delete-label = Couldn\u2019t delete. Refresh page and try again.\npdfjs-views-manager-status-warning-save-label = Couldn\u2019t save. Refresh page and try again.\npdfjs-views-manager-status-undo-button-label = Undo\npdfjs-views-manager-status-close-button =\n .title = Close\npdfjs-views-manager-status-close-button-label = Close";
3120
+ const text = "pdfjs-previous-button =\n .title = Previous Page\npdfjs-previous-button-label = Previous\npdfjs-next-button =\n .title = Next Page\npdfjs-next-button-label = Next\npdfjs-page-input =\n .title = Page\npdfjs-of-pages = of { $pagesCount }\npdfjs-page-of-pages = ({ $pageNumber } of { $pagesCount })\npdfjs-zoom-out-button =\n .title = Zoom Out\npdfjs-zoom-out-button-label = Zoom Out\npdfjs-zoom-in-button =\n .title = Zoom In\npdfjs-zoom-in-button-label = Zoom In\npdfjs-zoom-select =\n .title = Zoom\npdfjs-presentation-mode-button =\n .title = Switch to Presentation Mode\npdfjs-presentation-mode-button-label = Presentation Mode\npdfjs-open-file-button =\n .title = Open File\npdfjs-open-file-button-label = Open\npdfjs-print-button =\n .title = Print\npdfjs-print-button-label = Print\npdfjs-save-button =\n .title = Save\npdfjs-save-button-label = Save\npdfjs-download-button =\n .title = Download\npdfjs-download-button-label = Download\npdfjs-bookmark-button =\n .title = Current Page (View URL from Current Page)\npdfjs-bookmark-button-label = Current Page\npdfjs-tools-button =\n .title = Tools\npdfjs-tools-button-label = Tools\npdfjs-first-page-button =\n .title = Go to First Page\npdfjs-first-page-button-label = Go to First Page\npdfjs-last-page-button =\n .title = Go to Last Page\npdfjs-last-page-button-label = Go to Last Page\npdfjs-page-rotate-cw-button =\n .title = Rotate Clockwise\npdfjs-page-rotate-cw-button-label = Rotate Clockwise\npdfjs-page-rotate-ccw-button =\n .title = Rotate Counterclockwise\npdfjs-page-rotate-ccw-button-label = Rotate Counterclockwise\npdfjs-cursor-text-select-tool-button =\n .title = Enable Text Selection Tool\npdfjs-cursor-text-select-tool-button-label = Text Selection Tool\npdfjs-cursor-hand-tool-button =\n .title = Enable Hand Tool\npdfjs-cursor-hand-tool-button-label = Hand Tool\npdfjs-scroll-page-button =\n .title = Use Page Scrolling\npdfjs-scroll-page-button-label = Page Scrolling\npdfjs-scroll-vertical-button =\n .title = Use Vertical Scrolling\npdfjs-scroll-vertical-button-label = Vertical Scrolling\npdfjs-scroll-horizontal-button =\n .title = Use Horizontal Scrolling\npdfjs-scroll-horizontal-button-label = Horizontal Scrolling\npdfjs-scroll-wrapped-button =\n .title = Use Wrapped Scrolling\npdfjs-scroll-wrapped-button-label = Wrapped Scrolling\npdfjs-spread-none-button =\n .title = Do not join page spreads\npdfjs-spread-none-button-label = No Spreads\npdfjs-spread-odd-button =\n .title = Join page spreads starting with odd-numbered pages\npdfjs-spread-odd-button-label = Odd Spreads\npdfjs-spread-even-button =\n .title = Join page spreads starting with even-numbered pages\npdfjs-spread-even-button-label = Even Spreads\npdfjs-document-properties-button =\n .title = Document Properties\u2026\npdfjs-document-properties-button-label = Document Properties\u2026\npdfjs-document-properties-file-name = File name:\npdfjs-document-properties-file-size = File size:\npdfjs-document-properties-size-kb = { NUMBER($kb, maximumSignificantDigits: 3) } KB ({ $b } bytes)\npdfjs-document-properties-size-mb = { NUMBER($mb, maximumSignificantDigits: 3) } MB ({ $b } bytes)\npdfjs-document-properties-title = Title:\npdfjs-document-properties-author = Author:\npdfjs-document-properties-subject = Subject:\npdfjs-document-properties-keywords = Keywords:\npdfjs-document-properties-creation-date = Creation Date:\npdfjs-document-properties-modification-date = Modification Date:\npdfjs-document-properties-date-time-string = { DATETIME($dateObj, dateStyle: \"short\", timeStyle: \"medium\") }\npdfjs-document-properties-creator = Creator:\npdfjs-document-properties-producer = PDF Producer:\npdfjs-document-properties-version = PDF Version:\npdfjs-document-properties-page-count = Page Count:\npdfjs-document-properties-page-size = Page Size:\npdfjs-document-properties-page-size-unit-inches = in\npdfjs-document-properties-page-size-unit-millimeters = mm\npdfjs-document-properties-page-size-orientation-portrait = portrait\npdfjs-document-properties-page-size-orientation-landscape = landscape\npdfjs-document-properties-page-size-name-a-three = A3\npdfjs-document-properties-page-size-name-a-four = A4\npdfjs-document-properties-page-size-name-letter = Letter\npdfjs-document-properties-page-size-name-legal = Legal\npdfjs-document-properties-page-size-dimension-string = { $width } \xD7 { $height } { $unit } ({ $orientation })\npdfjs-document-properties-page-size-dimension-name-string = { $width } \xD7 { $height } { $unit } ({ $name }, { $orientation })\npdfjs-document-properties-linearized = Fast Web View:\npdfjs-document-properties-linearized-yes = Yes\npdfjs-document-properties-linearized-no = No\npdfjs-document-properties-close-button = Close\npdfjs-print-progress-message = Preparing document for printing\u2026\npdfjs-print-progress-percent = { $progress }%\npdfjs-print-progress-close-button = Cancel\npdfjs-printing-not-supported = Warning: Printing is not fully supported by this browser.\npdfjs-printing-not-ready = Warning: The PDF is not fully loaded for printing.\npdfjs-current-outline-item-button =\n .title = Find Current Outline Item\npdfjs-current-outline-item-button-label = Current Outline Item\npdfjs-findbar-button =\n .title = Find in Document\npdfjs-findbar-button-label = Find\npdfjs-additional-layers = Additional Layers\npdfjs-thumb-page-title1 =\n .title = Page { $page } of { $total }\npdfjs-thumb-page-canvas =\n .aria-label = Thumbnail of Page { $page }\npdfjs-thumb-page-checkbox1 =\n .title = Select page { $page }\npdfjs-find-input =\n .title = Find\n .placeholder = Find in document\u2026\npdfjs-find-previous-button =\n .title = Find the previous occurrence of the phrase\npdfjs-find-previous-button-label = Previous\npdfjs-find-next-button =\n .title = Find the next occurrence of the phrase\npdfjs-find-next-button-label = Next\npdfjs-find-highlight-checkbox = Highlight All\npdfjs-find-match-case-checkbox-label = Match Case\npdfjs-find-match-diacritics-checkbox-label = Match Diacritics\npdfjs-find-entire-word-checkbox-label = Whole Words\npdfjs-find-reached-top = Reached top of document, continued from bottom\npdfjs-find-reached-bottom = Reached end of document, continued from top\npdfjs-find-match-count =\n { $total ->\n [one] { $current } of { $total } match\n *[other] { $current } of { $total } matches\n }\npdfjs-find-match-count-limit =\n { $limit ->\n [one] More than { $limit } match\n *[other] More than { $limit } matches\n }\npdfjs-find-not-found = Phrase not found\npdfjs-page-scale-width = Page Width\npdfjs-page-scale-fit = Page Fit\npdfjs-page-scale-auto = Automatic Zoom\npdfjs-page-scale-actual = Actual Size\npdfjs-page-scale-percent = { $scale }%\npdfjs-page-landmark =\n .aria-label = Page { $page }\npdfjs-loading-error = An error occurred while loading the PDF.\npdfjs-invalid-file-error = Invalid or corrupted PDF file.\npdfjs-missing-file-error = Missing PDF file.\npdfjs-unexpected-response-error = Unexpected server response.\npdfjs-rendering-error = An error occurred while rendering the page.\npdfjs-annotation-date-time-string = { DATETIME($dateObj, dateStyle: \"short\", timeStyle: \"medium\") }\npdfjs-text-annotation-type =\n .alt = [{ $type } Annotation]\npdfjs-password-label = Enter the password to open this PDF file.\npdfjs-password-invalid = Invalid password. Please try again.\npdfjs-password-ok-button = OK\npdfjs-password-cancel-button = Cancel\npdfjs-web-fonts-disabled = Web fonts are disabled: unable to use embedded PDF fonts.\npdfjs-editor-free-text-button =\n .title = Text\npdfjs-editor-color-picker-free-text-input =\n .title = Change text color\npdfjs-editor-free-text-button-label = Text\npdfjs-editor-ink-button =\n .title = Draw\npdfjs-editor-color-picker-ink-input =\n .title = Change drawing color\npdfjs-editor-ink-button-label = Draw\npdfjs-editor-stamp-button =\n .title = Add or edit images\npdfjs-editor-stamp-button-label = Add or edit images\npdfjs-editor-highlight-button =\n .title = Highlight\npdfjs-editor-highlight-button-label = Highlight\npdfjs-highlight-floating-button1 =\n .title = Highlight\n .aria-label = Highlight\npdfjs-highlight-floating-button-label = Highlight\npdfjs-comment-floating-button =\n .title = Comment\n .aria-label = Comment\npdfjs-comment-floating-button-label = Comment\npdfjs-editor-comment-button =\n .title = Comment\n .aria-label = Comment\npdfjs-editor-comment-button-label = Comment\npdfjs-editor-signature-button =\n .title = Add signature\npdfjs-editor-signature-button-label = Add signature\npdfjs-editor-highlight-editor =\n .aria-label = Highlight editor\npdfjs-editor-ink-editor =\n .aria-label = Drawing editor\npdfjs-editor-signature-editor1 =\n .aria-description = Signature editor: { $description }\npdfjs-editor-stamp-editor =\n .aria-label = Image editor\npdfjs-editor-remove-ink-button =\n .title = Remove drawing\npdfjs-editor-remove-freetext-button =\n .title = Remove text\npdfjs-editor-remove-stamp-button =\n .title = Remove image\npdfjs-editor-remove-highlight-button =\n .title = Remove highlight\npdfjs-editor-remove-signature-button =\n .title = Remove signature\npdfjs-editor-free-text-color-input = Color\npdfjs-editor-free-text-size-input = Size\npdfjs-editor-ink-color-input = Color\npdfjs-editor-ink-thickness-input = Thickness\npdfjs-editor-ink-opacity-input = Opacity\npdfjs-editor-stamp-add-image-button =\n .title = Add image\npdfjs-editor-stamp-add-image-button-label = Add image\npdfjs-editor-free-highlight-thickness-input = Thickness\npdfjs-editor-free-highlight-thickness-title =\n .title = Change thickness when highlighting items other than text\npdfjs-editor-add-signature-container =\n .aria-label = Signature controls and saved signatures\npdfjs-editor-signature-add-signature-button =\n .title = Add new signature\npdfjs-editor-signature-add-signature-button-label = Add new signature\npdfjs-editor-add-saved-signature-button =\n .title = Saved signature: { $description }\npdfjs-free-text2 =\n .aria-label = Text Editor\n .default-content = Start typing\u2026\npdfjs-editor-comments-sidebar-title =\n { $count ->\n [one] Comment\n *[other] Comments\n }\npdfjs-editor-comments-sidebar-close-button =\n .title = Close the sidebar\n .aria-label = Close the sidebar\npdfjs-editor-comments-sidebar-close-button-label = Close the sidebar\npdfjs-editor-comments-sidebar-no-comments1 = See something noteworthy? Highlight it and leave a comment.\npdfjs-editor-comments-sidebar-no-comments-link = Learn more\npdfjs-editor-alt-text-button =\n .aria-label = Alt text\npdfjs-editor-alt-text-button-label = Alt text\npdfjs-editor-alt-text-edit-button =\n .aria-label = Edit alt text\npdfjs-editor-alt-text-dialog-label = Choose an option\npdfjs-editor-alt-text-dialog-description = Alt text (alternative text) helps when people can\u2019t see the image or when it doesn\u2019t load.\npdfjs-editor-alt-text-add-description-label = Add a description\npdfjs-editor-alt-text-add-description-description = Aim for 1-2 sentences that describe the subject, setting, or actions.\npdfjs-editor-alt-text-mark-decorative-label = Mark as decorative\npdfjs-editor-alt-text-mark-decorative-description = This is used for ornamental images, like borders or watermarks.\npdfjs-editor-alt-text-cancel-button = Cancel\npdfjs-editor-alt-text-save-button = Save\npdfjs-editor-alt-text-decorative-tooltip = Marked as decorative\npdfjs-editor-alt-text-textarea =\n .placeholder = For example, \u201CA young man sits down at a table to eat a meal\u201D\npdfjs-editor-resizer-top-left =\n .aria-label = Top left corner \u2014 resize\npdfjs-editor-resizer-top-middle =\n .aria-label = Top middle \u2014 resize\npdfjs-editor-resizer-top-right =\n .aria-label = Top right corner \u2014 resize\npdfjs-editor-resizer-middle-right =\n .aria-label = Middle right \u2014 resize\npdfjs-editor-resizer-bottom-right =\n .aria-label = Bottom right corner \u2014 resize\npdfjs-editor-resizer-bottom-middle =\n .aria-label = Bottom middle \u2014 resize\npdfjs-editor-resizer-bottom-left =\n .aria-label = Bottom left corner \u2014 resize\npdfjs-editor-resizer-middle-left =\n .aria-label = Middle left \u2014 resize\npdfjs-editor-highlight-colorpicker-label = Highlight color\npdfjs-editor-colorpicker-button =\n .title = Change color\npdfjs-editor-colorpicker-dropdown =\n .aria-label = Color choices\npdfjs-editor-colorpicker-yellow =\n .title = Yellow\npdfjs-editor-colorpicker-green =\n .title = Green\npdfjs-editor-colorpicker-blue =\n .title = Blue\npdfjs-editor-colorpicker-pink =\n .title = Pink\npdfjs-editor-colorpicker-red =\n .title = Red\npdfjs-editor-highlight-show-all-button-label = Show all\npdfjs-editor-highlight-show-all-button =\n .title = Show all\npdfjs-editor-new-alt-text-dialog-edit-label = Edit alt text (image description)\npdfjs-editor-new-alt-text-dialog-add-label = Add alt text (image description)\npdfjs-editor-new-alt-text-textarea =\n .placeholder = Write your description here\u2026\npdfjs-editor-new-alt-text-description = Short description for people who can\u2019t see the image or when the image doesn\u2019t load.\npdfjs-editor-new-alt-text-disclaimer1 = This alt text was created automatically and may be inaccurate.\npdfjs-editor-new-alt-text-disclaimer-learn-more-url = Learn more\npdfjs-editor-new-alt-text-create-automatically-button-label = Create alt text automatically\npdfjs-editor-new-alt-text-not-now-button = Not now\npdfjs-editor-new-alt-text-error-title = Couldn\u2019t create alt text automatically\npdfjs-editor-new-alt-text-error-description = Please write your own alt text or try again later.\npdfjs-editor-new-alt-text-error-close-button = Close\npdfjs-editor-new-alt-text-ai-model-downloading-progress = Downloading alt text AI model ({ $downloadedSize } of { $totalSize } MB)\n .aria-valuetext = Downloading alt text AI model ({ $downloadedSize } of { $totalSize } MB)\npdfjs-editor-new-alt-text-added-button =\n .aria-label = Alt text added\npdfjs-editor-new-alt-text-added-button-label = Alt text added\npdfjs-editor-new-alt-text-missing-button =\n .aria-label = Missing alt text\npdfjs-editor-new-alt-text-missing-button-label = Missing alt text\npdfjs-editor-new-alt-text-to-review-button =\n .aria-label = Review alt text\npdfjs-editor-new-alt-text-to-review-button-label = Review alt text\npdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer = Created automatically: { $generatedAltText }\npdfjs-image-alt-text-settings-button =\n .title = Image alt text settings\npdfjs-image-alt-text-settings-button-label = Image alt text settings\npdfjs-editor-alt-text-settings-dialog-label = Image alt text settings\npdfjs-editor-alt-text-settings-automatic-title = Automatic alt text\npdfjs-editor-alt-text-settings-create-model-button-label = Create alt text automatically\npdfjs-editor-alt-text-settings-create-model-description = Suggests descriptions to help people who can\u2019t see the image or when the image doesn\u2019t load.\npdfjs-editor-alt-text-settings-editor-title = Alt text editor\npdfjs-editor-alt-text-settings-show-dialog-button-label = Show alt text editor right away when adding an image\npdfjs-editor-alt-text-settings-show-dialog-description = Helps you make sure all your images have alt text.\npdfjs-editor-alt-text-settings-close-button = Close\npdfjs-editor-highlight-added-alert = Highlight added\npdfjs-editor-freetext-added-alert = Text added\npdfjs-editor-ink-added-alert = Drawing added\npdfjs-editor-stamp-added-alert = Image added\npdfjs-editor-signature-added-alert = Signature added\npdfjs-editor-undo-bar-message-highlight = Highlight removed\npdfjs-editor-undo-bar-message-freetext = Text removed\npdfjs-editor-undo-bar-message-ink = Drawing removed\npdfjs-editor-undo-bar-message-stamp = Image removed\npdfjs-editor-undo-bar-message-signature = Signature removed\npdfjs-editor-undo-bar-message-comment = Comment removed\npdfjs-editor-undo-bar-message-multiple =\n { $count ->\n [one] { $count } annotation removed\n *[other] { $count } annotations removed\n }\npdfjs-editor-undo-bar-undo-button =\n .title = Undo\npdfjs-editor-undo-bar-undo-button-label = Undo\npdfjs-editor-undo-bar-close-button =\n .title = Close\npdfjs-editor-undo-bar-close-button-label = Close\npdfjs-editor-add-signature-dialog-label = This modal allows the user to create a signature to add to a PDF document. The user can edit the name (which also serves as the alt text), and optionally save the signature for repeated use.\npdfjs-editor-add-signature-dialog-title = Add a signature\npdfjs-editor-add-signature-type-button = Type\n .title = Type\npdfjs-editor-add-signature-draw-button = Draw\n .title = Draw\npdfjs-editor-add-signature-image-button = Image\n .title = Image\npdfjs-editor-add-signature-type-input =\n .aria-label = Type your signature\n .placeholder = Type your signature\npdfjs-editor-add-signature-draw-placeholder = Draw your signature\npdfjs-editor-add-signature-draw-thickness-range-label = Thickness\npdfjs-editor-add-signature-draw-thickness-range =\n .title = Drawing thickness: { $thickness }\npdfjs-editor-add-signature-image-placeholder = Drag a file here to upload\npdfjs-editor-add-signature-image-browse-link =\n { PLATFORM() ->\n [macos] Or choose image files\n *[other] Or browse image files\n }\npdfjs-editor-add-signature-description-label = Description (alt text)\npdfjs-editor-add-signature-description-input =\n .title = Description (alt text)\npdfjs-editor-add-signature-description-default-when-drawing = Signature\npdfjs-editor-add-signature-clear-button-label = Clear signature\npdfjs-editor-add-signature-clear-button =\n .title = Clear signature\npdfjs-editor-add-signature-save-checkbox = Save signature\npdfjs-editor-add-signature-save-warning-message = You\u2019ve reached the limit of 5 saved signatures. Remove one to save more.\npdfjs-editor-add-signature-image-upload-error-title = Couldn\u2019t upload image\npdfjs-editor-add-signature-image-upload-error-description = Check your network connection or try another image.\npdfjs-editor-add-signature-image-no-data-error-title = Can\u2019t convert this image into a signature\npdfjs-editor-add-signature-image-no-data-error-description = Please try uploading a different image.\npdfjs-editor-add-signature-error-close-button = Close\npdfjs-editor-add-signature-cancel-button = Cancel\npdfjs-editor-add-signature-add-button = Add\npdfjs-editor-delete-signature-button1 =\n .title = Remove saved signature\npdfjs-editor-delete-signature-button-label1 = Remove saved signature\npdfjs-editor-add-signature-edit-button-label = Edit description\npdfjs-editor-edit-signature-dialog-title = Edit description\npdfjs-editor-edit-signature-update-button = Update\npdfjs-show-comment-button =\n .title = Show comment\npdfjs-editor-edit-comment-popup-button-label = Edit comment\npdfjs-editor-edit-comment-popup-button =\n .title = Edit comment\npdfjs-editor-delete-comment-popup-button-label = Remove comment\npdfjs-editor-delete-comment-popup-button =\n .title = Remove comment\npdfjs-editor-edit-comment-dialog-title-when-editing = Edit comment\npdfjs-editor-edit-comment-dialog-save-button-when-editing = Update\npdfjs-editor-edit-comment-dialog-title-when-adding = Add comment\npdfjs-editor-edit-comment-dialog-save-button-when-adding = Add\npdfjs-editor-edit-comment-dialog-text-input =\n .placeholder = Start typing\u2026\npdfjs-editor-edit-comment-dialog-cancel-button = Cancel\npdfjs-editor-add-comment-button =\n .title = Add comment\npdfjs-toggle-views-manager-button1 =\n .title = Manage pages\npdfjs-toggle-views-manager-notification-button =\n .title = Toggle Sidebar (document contains thumbnails/outline/attachments/layers)\npdfjs-toggle-views-manager-button1-label = Manage pages\npdfjs-views-manager-sidebar =\n .aria-label = Sidebar\npdfjs-views-manager-sidebar-resizer =\n .aria-label = Sidebar resizer\npdfjs-views-manager-view-selector-button =\n .title = Views\npdfjs-views-manager-view-selector-button-label = Views\npdfjs-views-manager-pages-title = Pages\npdfjs-views-manager-outlines-title = Document outline\npdfjs-views-manager-attachments-title = Attachments\npdfjs-views-manager-layers-title = Layers\npdfjs-views-manager-pages-option-label = Pages\npdfjs-views-manager-outlines-option-label = Document outline\npdfjs-views-manager-attachments-option-label = Attachments\npdfjs-views-manager-layers-option-label = Layers\npdfjs-views-manager-add-file-button =\n .title = Add file\npdfjs-views-manager-add-file-button-label = Add file\npdfjs-views-manager-pages-status-action-label =\n { $count ->\n [one] { $count } selected\n *[other] { $count } selected\n }\npdfjs-views-manager-pages-status-none-action-label = Select pages\npdfjs-views-manager-pages-status-action-button-label = Manage\npdfjs-views-manager-pages-status-copy-button-label = Copy\npdfjs-views-manager-pages-status-cut-button-label = Cut\npdfjs-views-manager-pages-status-delete-button-label = Delete\npdfjs-views-manager-pages-status-save-as-button-label = Save as\u2026\npdfjs-views-manager-status-undo-cut-label =\n { $count ->\n [one] 1 page cut\n *[other] { $count } pages cut\n }\npdfjs-views-manager-pages-status-undo-copy-label =\n { $count ->\n [one] 1 page copied\n *[other] { $count } pages copied\n }\npdfjs-views-manager-pages-status-undo-delete-label =\n { $count ->\n [one] 1 page deleted\n *[other] { $count } pages deleted\n }\npdfjs-views-manager-pages-status-waiting-ready-label = Getting your file ready\u2026\npdfjs-views-manager-pages-status-waiting-uploading-label = Uploading file\u2026\npdfjs-views-manager-status-warning-cut-label = Couldn\u2019t cut. Refresh page and try again.\npdfjs-views-manager-status-warning-copy-label = Couldn\u2019t copy. Refresh page and try again.\npdfjs-views-manager-status-warning-delete-label = Couldn\u2019t delete. Refresh page and try again.\npdfjs-views-manager-status-warning-save-label = Couldn\u2019t save. Refresh page and try again.\npdfjs-views-manager-status-undo-button-label = Undo\npdfjs-views-manager-status-close-button =\n .title = Close\npdfjs-views-manager-status-close-button-label = Close\npdfjs-views-manager-paste-button-label = Paste";
3125
3121
  return createBundle(lang, text);
3126
3122
  }
3127
3123
  }
3128
3124
 
3129
3125
  ;// ./web/generic_scripting.js
3126
+ /* unused harmony import specifier */ var generic_scripting_getPdfFilenameFromUrl;
3130
3127
 
3131
3128
  async function docProperties(pdfDocument) {
3132
3129
  const url = "",
@@ -3141,7 +3138,7 @@ async function docProperties(pdfDocument) {
3141
3138
  ...info,
3142
3139
  baseURL: baseUrl,
3143
3140
  filesize: contentLength || (await pdfDocument.getDownloadInfo()).length,
3144
- filename: contentDispositionFilename || getPdfFilenameFromUrl(url),
3141
+ filename: contentDispositionFilename || generic_scripting_getPdfFilenameFromUrl(url),
3145
3142
  metadata: metadata?.getRaw(),
3146
3143
  authors: metadata?.get("dc:creator"),
3147
3144
  numPages: pdfDocument.numPages,
@@ -3363,7 +3360,20 @@ class NewAltTextManager {
3363
3360
  }
3364
3361
  });
3365
3362
  if (this.#uiManager) {
3366
- this.#uiManager.setPreference("enableGuessAltText", checked);
3363
+ const isAltTextEnabled = await this.#uiManager.mlManager.isEnabledFor("altText");
3364
+ this.#createAutomaticallyButton.disabled = true;
3365
+ if (checked && !isAltTextEnabled) {
3366
+ this.#textarea.value = "";
3367
+ this.#setProgress();
3368
+ this.#uiManager.setPreference("enableGuessAltText", true);
3369
+ await this.#uiManager.mlManager.downloadModel("altText");
3370
+ this.#setPref("enableAltTextModelDownload", true);
3371
+ } else if (!checked && isAltTextEnabled) {
3372
+ this.#uiManager.setPreference("enableGuessAltText", false);
3373
+ await this.#uiManager.mlManager.deleteModel("altText");
3374
+ this.#setPref("enableAltTextModelDownload", false);
3375
+ }
3376
+ this.#createAutomaticallyButton.disabled = false;
3367
3377
  await this.#uiManager.mlManager.toggleService("altText", checked);
3368
3378
  }
3369
3379
  this.#toggleGuessAltText(checked, false);
@@ -3402,6 +3412,13 @@ class NewAltTextManager {
3402
3412
  });
3403
3413
  });
3404
3414
  }
3415
+ #setPref(name, value) {
3416
+ this.#eventBus.dispatch("setpreference", {
3417
+ source: this,
3418
+ name,
3419
+ value
3420
+ });
3421
+ }
3405
3422
  #toggleLoading(value) {
3406
3423
  if (!this.#uiManager || this.#isAILoading === value) {
3407
3424
  return;
@@ -3415,7 +3432,7 @@ class NewAltTextManager {
3415
3432
  }
3416
3433
  this.#dialog.classList.toggle("error", value);
3417
3434
  }
3418
- async #toggleGuessAltText(value, isInitial = false) {
3435
+ async #toggleGuessAltText(value, isInitial) {
3419
3436
  if (!this.#uiManager) {
3420
3437
  return;
3421
3438
  }
@@ -3544,17 +3561,16 @@ class NewAltTextManager {
3544
3561
  return;
3545
3562
  }
3546
3563
  this.#firstTime = firstTime;
3547
- let {
3564
+ const {
3548
3565
  mlManager
3549
3566
  } = uiManager;
3550
- let hasAI = !!mlManager;
3567
+ const hasAI = !!mlManager;
3551
3568
  this.#toggleTitleAndDisclaimer();
3552
3569
  if (mlManager && !mlManager.isReady("altText")) {
3553
- hasAI = false;
3554
3570
  if (mlManager.hasProgress) {
3555
3571
  this.#setProgress();
3556
3572
  } else {
3557
- mlManager = null;
3573
+ this.#createAutomaticallyButton.setAttribute("aria-pressed", false);
3558
3574
  }
3559
3575
  } else {
3560
3576
  this.#downloadModel.classList.toggle("hidden", true);
@@ -3684,9 +3700,7 @@ class NewAltTextManager {
3684
3700
  }
3685
3701
  }
3686
3702
  class ImageAltTextSettings {
3687
- #aiModelSettings;
3688
3703
  #createModelButton;
3689
- #downloadModelButton;
3690
3704
  #dialog;
3691
3705
  #eventBus;
3692
3706
  #mlManager;
@@ -3695,17 +3709,12 @@ class ImageAltTextSettings {
3695
3709
  constructor({
3696
3710
  dialog,
3697
3711
  createModelButton,
3698
- aiModelSettings,
3699
3712
  learnMore,
3700
3713
  closeButton,
3701
- deleteModelButton,
3702
- downloadModelButton,
3703
3714
  showAltTextDialogButton
3704
3715
  }, overlayManager, eventBus, mlManager) {
3705
3716
  this.#dialog = dialog;
3706
- this.#aiModelSettings = aiModelSettings;
3707
3717
  this.#createModelButton = createModelButton;
3708
- this.#downloadModelButton = downloadModelButton;
3709
3718
  this.#showAltTextDialogButton = showAltTextDialogButton;
3710
3719
  this.#overlayManager = overlayManager;
3711
3720
  this.#eventBus = eventBus;
@@ -3719,6 +3728,7 @@ class ImageAltTextSettings {
3719
3728
  dialog.addEventListener("contextmenu", noContextMenu);
3720
3729
  createModelButton.addEventListener("click", async e => {
3721
3730
  const checked = this.#togglePref("enableGuessAltText", e);
3731
+ await (checked ? this.#download(true) : this.#delete(true));
3722
3732
  await mlManager.toggleService("altText", checked);
3723
3733
  this.#reportTelemetry({
3724
3734
  type: "stamp",
@@ -3738,8 +3748,6 @@ class ImageAltTextSettings {
3738
3748
  }
3739
3749
  });
3740
3750
  });
3741
- deleteModelButton.addEventListener("click", this.#delete.bind(this, true));
3742
- downloadModelButton.addEventListener("click", this.#download.bind(this, true));
3743
3751
  closeButton.addEventListener("click", this.#finish.bind(this));
3744
3752
  learnMore.addEventListener("click", () => {
3745
3753
  this.#reportTelemetry({
@@ -3772,19 +3780,11 @@ class ImageAltTextSettings {
3772
3780
  }
3773
3781
  async #download(isFromUI = false) {
3774
3782
  if (isFromUI) {
3775
- this.#downloadModelButton.disabled = true;
3776
- const span = this.#downloadModelButton.firstElementChild;
3777
- span.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-settings-downloading-model-button");
3778
3783
  await this.#mlManager.downloadModel("altText");
3779
- span.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-settings-download-model-button");
3780
- this.#createModelButton.disabled = false;
3781
3784
  this.#setPref("enableGuessAltText", true);
3782
3785
  this.#mlManager.toggleService("altText", true);
3783
3786
  this.#setPref("enableAltTextModelDownload", true);
3784
- this.#downloadModelButton.disabled = false;
3785
3787
  }
3786
- this.#aiModelSettings.classList.toggle("download", false);
3787
- this.#createModelButton.setAttribute("aria-pressed", true);
3788
3788
  }
3789
3789
  async #delete(isFromUI = false) {
3790
3790
  if (isFromUI) {
@@ -3792,8 +3792,6 @@ class ImageAltTextSettings {
3792
3792
  this.#setPref("enableGuessAltText", false);
3793
3793
  this.#setPref("enableAltTextModelDownload", false);
3794
3794
  }
3795
- this.#aiModelSettings.classList.toggle("download", true);
3796
- this.#createModelButton.disabled = true;
3797
3795
  this.#createModelButton.setAttribute("aria-pressed", false);
3798
3796
  }
3799
3797
  async open({
@@ -3803,10 +3801,8 @@ class ImageAltTextSettings {
3803
3801
  const {
3804
3802
  enableAltTextModelDownload
3805
3803
  } = this.#mlManager;
3806
- this.#createModelButton.disabled = !enableAltTextModelDownload;
3807
3804
  this.#createModelButton.setAttribute("aria-pressed", enableAltTextModelDownload && enableGuessAltText);
3808
3805
  this.#showAltTextDialogButton.setAttribute("aria-pressed", enableNewAltTextWhenAddingImage);
3809
- this.#aiModelSettings.classList.toggle("download", !enableAltTextModelDownload);
3810
3806
  await this.#overlayManager.open(this.#dialog);
3811
3807
  this.#reportTelemetry({
3812
3808
  type: "stamp",
@@ -5529,47 +5525,31 @@ class CommentPopup {
5529
5525
  }
5530
5526
  }
5531
5527
 
5532
- ;// ./web/download_manager.js
5528
+ ;// ./web/base_download_manager.js
5533
5529
 
5534
- function download(blobUrl, filename) {
5535
- const a = document.createElement("a");
5536
- if (!a.click) {
5537
- throw new Error('DownloadManager: "a.click()" is not supported.');
5538
- }
5539
- a.href = blobUrl;
5540
- a.target = "_parent";
5541
- if ("download" in a) {
5542
- a.download = filename;
5543
- }
5544
- (document.body || document.documentElement).append(a);
5545
- a.click();
5546
- a.remove();
5547
- }
5548
- class DownloadManager {
5530
+ class BaseDownloadManager {
5549
5531
  #openBlobUrls = new WeakMap();
5532
+ _triggerDownload(blobUrl, originalUrl, filename, isAttachment = false) {
5533
+ throw new Error("Not implemented: _triggerDownload");
5534
+ }
5535
+ _getOpenDataUrl(blobUrl, filename, dest = null) {
5536
+ throw new Error("Not implemented: _getOpenDataUrl");
5537
+ }
5550
5538
  downloadData(data, filename, contentType) {
5551
5539
  const blobUrl = URL.createObjectURL(new Blob([data], {
5552
5540
  type: contentType
5553
5541
  }));
5554
- download(blobUrl, filename);
5542
+ this._triggerDownload(blobUrl, blobUrl, filename, true);
5555
5543
  }
5556
5544
  openOrDownloadData(data, filename, dest = null) {
5557
5545
  const isPdfData = isPdfFile(filename);
5558
5546
  const contentType = isPdfData ? "application/pdf" : "";
5559
5547
  if (isPdfData) {
5560
- let blobUrl = this.#openBlobUrls.get(data);
5561
- if (!blobUrl) {
5562
- blobUrl = URL.createObjectURL(new Blob([data], {
5563
- type: contentType
5564
- }));
5565
- this.#openBlobUrls.set(data, blobUrl);
5566
- }
5567
- let viewerUrl;
5568
- viewerUrl = "?file=" + encodeURIComponent(blobUrl + "#" + filename);
5569
- if (dest) {
5570
- viewerUrl += `#${escape(dest)}`;
5571
- }
5548
+ const blobUrl = this.#openBlobUrls.getOrInsertComputed(data, () => URL.createObjectURL(new Blob([data], {
5549
+ type: contentType
5550
+ })));
5572
5551
  try {
5552
+ const viewerUrl = this._getOpenDataUrl(blobUrl, filename, dest);
5573
5553
  window.open(viewerUrl);
5574
5554
  return true;
5575
5555
  } catch (ex) {
@@ -5582,19 +5562,40 @@ class DownloadManager {
5582
5562
  return false;
5583
5563
  }
5584
5564
  download(data, url, filename) {
5585
- let blobUrl;
5586
- if (data) {
5587
- blobUrl = URL.createObjectURL(new Blob([data], {
5588
- type: "application/pdf"
5589
- }));
5590
- } else {
5591
- if (!createValidAbsoluteUrl(url, "http://example.com")) {
5592
- console.error(`download - not a valid URL: ${url}`);
5593
- return;
5565
+ const blobUrl = data ? URL.createObjectURL(new Blob([data], {
5566
+ type: "application/pdf"
5567
+ })) : null;
5568
+ this._triggerDownload(blobUrl, url, filename);
5569
+ }
5570
+ }
5571
+
5572
+ ;// ./web/download_manager.js
5573
+
5574
+
5575
+ class DownloadManager extends BaseDownloadManager {
5576
+ _triggerDownload(blobUrl, originalUrl, filename, isAttachment = false) {
5577
+ if (!blobUrl && !isAttachment) {
5578
+ if (!createValidAbsoluteUrl(originalUrl, "http://example.com")) {
5579
+ throw new Error(`_triggerDownload - not a valid URL: ${originalUrl}`);
5594
5580
  }
5595
- blobUrl = url + "#pdfjs.action=download";
5581
+ blobUrl = originalUrl + "#pdfjs.action=download";
5596
5582
  }
5597
- download(blobUrl, filename);
5583
+ const a = document.createElement("a");
5584
+ a.href = blobUrl;
5585
+ a.target = "_parent";
5586
+ if ("download" in a) {
5587
+ a.download = filename;
5588
+ }
5589
+ (document.body || document.documentElement).append(a);
5590
+ a.click();
5591
+ a.remove();
5592
+ }
5593
+ _getOpenDataUrl(blobUrl, filename, dest = null) {
5594
+ let url = "?file=" + encodeURIComponent(blobUrl + "#" + filename);
5595
+ if (dest) {
5596
+ url += `#${escape(dest)}`;
5597
+ }
5598
+ return url;
5598
5599
  }
5599
5600
  }
5600
5601
 
@@ -5816,7 +5817,6 @@ class PasswordPrompt {
5816
5817
  ;// ./web/base_tree_viewer.js
5817
5818
 
5818
5819
 
5819
- const TREEITEM_OFFSET_TOP = -100;
5820
5820
  const TREEITEM_SELECTED_CLASS = "selected";
5821
5821
  class BaseTreeViewer {
5822
5822
  constructor(options) {
@@ -5875,7 +5875,7 @@ class BaseTreeViewer {
5875
5875
  target.classList.toggle("treeItemsHidden");
5876
5876
  if (e.shiftKey) {
5877
5877
  const shouldShowAll = !target.classList.contains("treeItemsHidden");
5878
- this._toggleTreeItem(this.container, shouldShowAll);
5878
+ this._toggleTreeItem(target.parentNode, shouldShowAll);
5879
5879
  }
5880
5880
  });
5881
5881
  }
@@ -5912,7 +5912,12 @@ class BaseTreeViewer {
5912
5912
  }
5913
5913
  this._l10n.resume();
5914
5914
  this._updateCurrentTreeItem(treeItem);
5915
- this.container.scrollTo(treeItem.offsetLeft, treeItem.offsetTop + TREEITEM_OFFSET_TOP);
5915
+ treeItem.scrollIntoView({
5916
+ behavior: "instant",
5917
+ block: "center",
5918
+ inline: "center",
5919
+ container: "nearest"
5920
+ });
5916
5921
  }
5917
5922
  }
5918
5923
 
@@ -6495,6 +6500,45 @@ function getCharacterType(charCode) {
6495
6500
  }
6496
6501
  let NormalizeWithNFKC;
6497
6502
  function getNormalizeWithNFKC() {
6503
+ if (!NormalizeWithNFKC) {
6504
+ const ranges = [];
6505
+ const range = [];
6506
+ const diacriticsRegex = /^\p{M}$/u;
6507
+ for (let i = 0; i < 65536; i++) {
6508
+ if (i >= 0xd800 && i <= 0xdfff) {
6509
+ continue;
6510
+ }
6511
+ const c = String.fromCharCode(i);
6512
+ if (c.normalize("NFKC") !== c && !diacriticsRegex.test(c)) {
6513
+ if (range.length !== 2) {
6514
+ range[0] = range[1] = i;
6515
+ continue;
6516
+ }
6517
+ if (range[1] + 1 !== i) {
6518
+ if (range[0] === range[1]) {
6519
+ ranges.push(String.fromCharCode(range[0]));
6520
+ } else {
6521
+ ranges.push(`${String.fromCharCode(range[0])}-${String.fromCharCode(range[1])}`);
6522
+ }
6523
+ range[0] = range[1] = i;
6524
+ } else {
6525
+ range[1] = i;
6526
+ }
6527
+ }
6528
+ }
6529
+ const rangesStr = ranges.join("");
6530
+ if (!NormalizeWithNFKC) {
6531
+ NormalizeWithNFKC = rangesStr;
6532
+ } else if (rangesStr !== NormalizeWithNFKC) {
6533
+ for (let i = 1; i < rangesStr.length; i++) {
6534
+ if (rangesStr[i] !== NormalizeWithNFKC[i]) {
6535
+ console.log(`Difference at index ${i}: ` + `U+${rangesStr.charCodeAt(i).toString(16).toUpperCase().padStart(4, "0")}` + `!== U+${NormalizeWithNFKC.charCodeAt(i).toString(16).toUpperCase().padStart(4, "0")}`);
6536
+ break;
6537
+ }
6538
+ }
6539
+ throw new Error("getNormalizeWithNFKC - update the `NormalizeWithNFKC` string.");
6540
+ }
6541
+ }
6498
6542
  return NormalizeWithNFKC;
6499
6543
  }
6500
6544
 
@@ -6722,6 +6766,7 @@ class PDFFindController {
6722
6766
  #state = null;
6723
6767
  #updateMatchesCountOnProgress = true;
6724
6768
  #visitedPagesCount = 0;
6769
+ #copiedExtractTextPromises = null;
6725
6770
  constructor({
6726
6771
  linkService,
6727
6772
  eventBus,
@@ -6859,6 +6904,7 @@ class PDFFindController {
6859
6904
  this._dirtyMatch = false;
6860
6905
  clearTimeout(this._findTimeout);
6861
6906
  this._findTimeout = null;
6907
+ this.#copiedExtractTextPromises = null;
6862
6908
  this._firstPageCapability = Promise.withResolvers();
6863
6909
  }
6864
6910
  get #query() {
@@ -7212,21 +7258,31 @@ class PDFFindController {
7212
7258
  }
7213
7259
  }
7214
7260
  #onPagesEdited({
7215
- pagesMapper
7261
+ pagesMapper,
7262
+ type,
7263
+ pageNumbers
7216
7264
  }) {
7217
7265
  if (this._extractTextPromises.length === 0) {
7218
7266
  return;
7219
7267
  }
7268
+ if (type === "copy") {
7269
+ this.#copiedExtractTextPromises = new Map();
7270
+ for (const pageNum of pageNumbers) {
7271
+ this.#copiedExtractTextPromises.set(pageNum, this._extractTextPromises[pageNum - 1]);
7272
+ }
7273
+ return;
7274
+ }
7220
7275
  this.#onFindBarClose();
7221
7276
  this._dirtyMatch = true;
7222
7277
  const prevTextPromises = this._extractTextPromises;
7223
7278
  const extractTextPromises = this._extractTextPromises.length = [];
7224
- for (let i = 0, ii = pagesMapper.length; i < ii; i++) {
7225
- const prevPageIndex = pagesMapper.getPrevPageNumber(i + 1) - 1;
7226
- if (prevPageIndex === -1) {
7279
+ for (let i = 1, ii = pagesMapper.length; i <= ii; i++) {
7280
+ const prevPageNumber = pagesMapper.getPrevPageNumber(i);
7281
+ if (prevPageNumber < 0) {
7282
+ extractTextPromises.push(this.#copiedExtractTextPromises?.get(-prevPageNumber) || Promise.resolve());
7227
7283
  continue;
7228
7284
  }
7229
- extractTextPromises.push(prevTextPromises[prevPageIndex] || Promise.resolve());
7285
+ extractTextPromises.push(prevTextPromises[prevPageNumber - 1] || Promise.resolve());
7230
7286
  }
7231
7287
  }
7232
7288
  #onFindBarClose(evt) {
@@ -7297,8 +7353,8 @@ const MATCHES_COUNT_LIMIT = 1000;
7297
7353
  class PDFFindBar {
7298
7354
  #mainContainer;
7299
7355
  #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
7356
+ opened = false;
7300
7357
  constructor(options, mainContainer, eventBus) {
7301
- this.opened = false;
7302
7358
  this.bar = options.bar;
7303
7359
  this.toggleButton = options.toggleButton;
7304
7360
  this.findField = options.findField;
@@ -8726,6 +8782,15 @@ class XfaLayerBuilder {
8726
8782
 
8727
8783
 
8728
8784
 
8785
+ class BasePrintServiceFactory {
8786
+ static initGlobals(app) {}
8787
+ static get supportsPrinting() {
8788
+ throw new Error("Not implemented: supportsPrinting");
8789
+ }
8790
+ static createPrintService(params) {
8791
+ throw new Error("Not implemented: createPrintService");
8792
+ }
8793
+ }
8729
8794
  function getXfaHtmlForPrinting(printContainer, pdfDocument) {
8730
8795
  const xfaHtml = pdfDocument.allXfaHtml;
8731
8796
  const linkService = new SimpleLinkService();
@@ -8993,7 +9058,7 @@ function ensureOverlay() {
8993
9058
  }
8994
9059
  return overlayPromise;
8995
9060
  }
8996
- class PDFPrintServiceFactory {
9061
+ class PDFPrintServiceFactory extends BasePrintServiceFactory {
8997
9062
  static initGlobals(app) {
8998
9063
  viewerApp = app;
8999
9064
  }
@@ -9008,48 +9073,70 @@ class PDFPrintServiceFactory {
9008
9073
  }
9009
9074
  }
9010
9075
 
9076
+ ;// ./web/renderable_view.js
9077
+ const RenderingStates = {
9078
+ INITIAL: 0,
9079
+ RUNNING: 1,
9080
+ PAUSED: 2,
9081
+ FINISHED: 3
9082
+ };
9083
+ class RenderableView {
9084
+ renderingId = "";
9085
+ renderTask = null;
9086
+ resume = null;
9087
+ get renderingState() {
9088
+ throw new Error("Abstract getter `renderingState` accessed");
9089
+ }
9090
+ set renderingState(state) {
9091
+ throw new Error("Abstract setter `renderingState` accessed");
9092
+ }
9093
+ async draw() {
9094
+ throw new Error("Not implemented: draw");
9095
+ }
9096
+ }
9097
+
9011
9098
  ;// ./web/pdf_rendering_queue.js
9012
9099
 
9013
9100
 
9014
9101
  const CLEANUP_TIMEOUT = 30000;
9015
9102
  class PDFRenderingQueue {
9103
+ #highestPriorityPage = null;
9104
+ #idleTimeout = null;
9105
+ #pdfThumbnailViewer = null;
9106
+ #pdfViewer = null;
9107
+ isThumbnailViewEnabled = false;
9108
+ onIdle = null;
9109
+ printing = false;
9016
9110
  constructor() {
9017
- this.pdfViewer = null;
9018
- this.pdfThumbnailViewer = null;
9019
- this.onIdle = null;
9020
- this.highestPriorityPage = null;
9021
- this.idleTimeout = null;
9022
- this.printing = false;
9023
- this.isThumbnailViewEnabled = false;
9024
9111
  Object.defineProperty(this, "hasViewer", {
9025
- value: () => !!this.pdfViewer
9112
+ value: () => !!this.#pdfViewer
9026
9113
  });
9027
9114
  }
9028
9115
  setViewer(pdfViewer) {
9029
- this.pdfViewer = pdfViewer;
9116
+ this.#pdfViewer = pdfViewer;
9030
9117
  }
9031
9118
  setThumbnailViewer(pdfThumbnailViewer) {
9032
- this.pdfThumbnailViewer = pdfThumbnailViewer;
9119
+ this.#pdfThumbnailViewer = pdfThumbnailViewer;
9033
9120
  }
9034
9121
  isHighestPriority(view) {
9035
- return this.highestPriorityPage === view.renderingId;
9122
+ return this.#highestPriorityPage === view.renderingId;
9036
9123
  }
9037
9124
  renderHighestPriority(currentlyVisiblePages) {
9038
- if (this.idleTimeout) {
9039
- clearTimeout(this.idleTimeout);
9040
- this.idleTimeout = null;
9125
+ if (this.#idleTimeout) {
9126
+ clearTimeout(this.#idleTimeout);
9127
+ this.#idleTimeout = null;
9041
9128
  }
9042
- if (this.pdfViewer.forceRendering(currentlyVisiblePages)) {
9129
+ if (this.#pdfViewer.forceRendering(currentlyVisiblePages)) {
9043
9130
  return;
9044
9131
  }
9045
- if (this.isThumbnailViewEnabled && this.pdfThumbnailViewer?.forceRendering()) {
9132
+ if (this.isThumbnailViewEnabled && this.#pdfThumbnailViewer?.forceRendering()) {
9046
9133
  return;
9047
9134
  }
9048
9135
  if (this.printing) {
9049
9136
  return;
9050
9137
  }
9051
9138
  if (this.onIdle) {
9052
- this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
9139
+ this.#idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
9053
9140
  }
9054
9141
  }
9055
9142
  getHighestPriority(visible, views, scrolledDown, preRenderExtra = false, ignoreDetailViews = false) {
@@ -9111,14 +9198,14 @@ class PDFRenderingQueue {
9111
9198
  case RenderingStates.FINISHED:
9112
9199
  return false;
9113
9200
  case RenderingStates.PAUSED:
9114
- this.highestPriorityPage = view.renderingId;
9201
+ this.#highestPriorityPage = view.renderingId;
9115
9202
  view.resume();
9116
9203
  break;
9117
9204
  case RenderingStates.RUNNING:
9118
- this.highestPriorityPage = view.renderingId;
9205
+ this.#highestPriorityPage = view.renderingId;
9119
9206
  break;
9120
9207
  case RenderingStates.INITIAL:
9121
- this.highestPriorityPage = view.renderingId;
9208
+ this.#highestPriorityPage = view.renderingId;
9122
9209
  view.draw().finally(() => {
9123
9210
  this.renderHighestPriority();
9124
9211
  }).catch(reason => {
@@ -9136,6 +9223,7 @@ class PDFRenderingQueue {
9136
9223
  ;// ./web/pdf_scripting_manager.js
9137
9224
 
9138
9225
 
9226
+
9139
9227
  class PDFScriptingManager {
9140
9228
  #closeCapability = null;
9141
9229
  #destroyCapability = null;
@@ -9552,6 +9640,7 @@ class Menu {
9552
9640
  #openMenuAC = null;
9553
9641
  #menuAC = new AbortController();
9554
9642
  #lastIndex = -1;
9643
+ #onFocusOutBound = this.#onFocusOut.bind(this);
9555
9644
  constructor(menuContainer, triggeringButton, menuItems) {
9556
9645
  this.#menu = menuContainer;
9557
9646
  this.#triggeringButton = triggeringButton;
@@ -9582,29 +9671,47 @@ class Menu {
9582
9671
  }
9583
9672
  this.#lastIndex = -1;
9584
9673
  }
9674
+ #openMenu() {
9675
+ if (this.#openMenuAC) {
9676
+ return;
9677
+ }
9678
+ const menu = this.#menu;
9679
+ this.#triggeringButton.ariaExpanded = "true";
9680
+ this.#openMenuAC = new AbortController();
9681
+ const signal = AbortSignal.any([this.#menuAC.signal, this.#openMenuAC.signal]);
9682
+ window.addEventListener("pointerdown", ({
9683
+ target
9684
+ }) => {
9685
+ if (!this.#triggeringButton.contains(target) && !menu.contains(target)) {
9686
+ this.#closeMenu();
9687
+ }
9688
+ }, {
9689
+ signal
9690
+ });
9691
+ const closeMenu = this.#closeMenu.bind(this);
9692
+ window.addEventListener("blur", closeMenu, {
9693
+ signal
9694
+ });
9695
+ menu.addEventListener("focusout", this.#onFocusOutBound, {
9696
+ signal
9697
+ });
9698
+ }
9699
+ #onFocusOut({
9700
+ relatedTarget
9701
+ }) {
9702
+ if (!this.#triggeringButton.contains(relatedTarget) && !this.#menu.contains(relatedTarget)) {
9703
+ this.#closeMenu();
9704
+ }
9705
+ }
9585
9706
  #setUpMenu() {
9586
9707
  this.#triggeringButton.addEventListener("click", e => {
9587
9708
  if (this.#openMenuAC) {
9588
9709
  this.#closeMenu();
9589
9710
  return;
9590
9711
  }
9591
- const menu = this.#menu;
9592
- this.#triggeringButton.ariaExpanded = "true";
9593
- this.#openMenuAC = new AbortController();
9594
- const signal = AbortSignal.any([this.#menuAC.signal, this.#openMenuAC.signal]);
9595
- window.addEventListener("pointerdown", ({
9596
- target
9597
- }) => {
9598
- if (target !== this.#triggeringButton && !menu.contains(target)) {
9599
- this.#closeMenu();
9600
- }
9601
- }, {
9602
- signal
9603
- });
9604
- window.addEventListener("blur", this.#closeMenu.bind(this), {
9605
- signal
9606
- });
9712
+ this.#openMenu();
9607
9713
  });
9714
+ this.#triggeringButton.addEventListener("focusout", this.#onFocusOutBound);
9608
9715
  const {
9609
9716
  signal
9610
9717
  } = this.#menuAC;
@@ -9615,25 +9722,29 @@ class Menu {
9615
9722
  stopEvent(e);
9616
9723
  break;
9617
9724
  case "ArrowDown":
9618
- case "Tab":
9619
9725
  this.#goToNextItem(e.target, true);
9620
9726
  stopEvent(e);
9621
9727
  break;
9622
9728
  case "ArrowUp":
9623
- case "ShiftTab":
9624
9729
  this.#goToNextItem(e.target, false);
9625
9730
  stopEvent(e);
9626
9731
  break;
9627
9732
  case "Home":
9628
- this.#menuItems.find(item => !item.disabled && !item.classList.contains("hidden")).focus();
9733
+ this.#menuItems.find(item => !item.disabled && !item.classList.contains("hidden"))?.focus();
9629
9734
  stopEvent(e);
9630
9735
  break;
9631
9736
  case "End":
9632
- this.#menuItems.findLast(item => !item.disabled && !item.classList.contains("hidden")).focus();
9737
+ this.#menuItems.findLast(item => !item.disabled && !item.classList.contains("hidden"))?.focus();
9633
9738
  stopEvent(e);
9634
9739
  break;
9635
9740
  default:
9636
- const char = e.key.toLocaleLowerCase();
9741
+ const {
9742
+ key
9743
+ } = e;
9744
+ if (!/^\p{L}$/u.test(key)) {
9745
+ break;
9746
+ }
9747
+ const char = key.toLocaleLowerCase();
9637
9748
  this.#goToNextItem(e.target, true, item => item.textContent.trim().toLowerCase().startsWith(char));
9638
9749
  stopEvent(e);
9639
9750
  break;
@@ -9655,19 +9766,19 @@ class Menu {
9655
9766
  case "Enter":
9656
9767
  case "ArrowDown":
9657
9768
  case "Home":
9769
+ stopEvent(e);
9658
9770
  if (!this.#openMenuAC) {
9659
- this.#triggeringButton.click();
9771
+ this.#openMenu();
9660
9772
  }
9661
- this.#menuItems.find(item => !item.disabled && !item.classList.contains("hidden")).focus();
9662
- stopEvent(e);
9773
+ this.#menuItems.find(item => !item.disabled && !item.classList.contains("hidden"))?.focus();
9663
9774
  break;
9664
9775
  case "ArrowUp":
9665
9776
  case "End":
9777
+ stopEvent(e);
9666
9778
  if (!this.#openMenuAC) {
9667
- this.#triggeringButton.click();
9779
+ this.#openMenu();
9668
9780
  }
9669
- this.#menuItems.findLast(item => !item.disabled && !item.classList.contains("hidden")).focus();
9670
- stopEvent(e);
9781
+ this.#menuItems.findLast(item => !item.disabled && !item.classList.contains("hidden"))?.focus();
9671
9782
  break;
9672
9783
  case "Escape":
9673
9784
  this.#closeMenu();
@@ -9725,7 +9836,8 @@ class TempImageFactory {
9725
9836
  return [tempCanvas, ctx];
9726
9837
  }
9727
9838
  }
9728
- class PDFThumbnailView {
9839
+ class PDFThumbnailView extends RenderableView {
9840
+ #renderingState = RenderingStates.INITIAL;
9729
9841
  constructor({
9730
9842
  container,
9731
9843
  eventBus,
@@ -9739,6 +9851,7 @@ class PDFThumbnailView {
9739
9851
  pageColors,
9740
9852
  enableSplitMerge = false
9741
9853
  }) {
9854
+ super();
9742
9855
  this.id = id;
9743
9856
  this.renderingId = `thumbnail${id}`;
9744
9857
  this.pageLabel = null;
@@ -9753,33 +9866,82 @@ class PDFThumbnailView {
9753
9866
  this.eventBus = eventBus;
9754
9867
  this.linkService = linkService;
9755
9868
  this.renderingQueue = renderingQueue;
9756
- this.renderTask = null;
9757
- this.renderingState = RenderingStates.INITIAL;
9758
- this.resume = null;
9759
9869
  this.placeholder = null;
9760
- const imageContainer = this.div = document.createElement("div");
9761
- imageContainer.className = "thumbnail";
9870
+ const thumbnailContainer = this.div = document.createElement("div");
9871
+ thumbnailContainer.className = "thumbnail";
9872
+ thumbnailContainer.setAttribute("page-number", id);
9873
+ const imageContainer = this.imageContainer = document.createElement("div");
9874
+ thumbnailContainer.append(imageContainer);
9875
+ imageContainer.classList.add("thumbnailImageContainer", "missingThumbnailImage");
9876
+ imageContainer.role = "button";
9877
+ imageContainer.tabIndex = -1;
9878
+ imageContainer.draggable = false;
9762
9879
  imageContainer.setAttribute("page-number", id);
9763
- imageContainer.setAttribute("page-id", id);
9880
+ imageContainer.setAttribute("data-l10n-id", "pdfjs-thumb-page-title1");
9881
+ imageContainer.setAttribute("data-l10n-args", this.#getPageL10nArgs(true));
9882
+ const image = this.image = document.createElement("img");
9883
+ imageContainer.append(image);
9764
9884
  if (enableSplitMerge) {
9765
9885
  const checkbox = this.checkbox = document.createElement("input");
9766
9886
  checkbox.type = "checkbox";
9767
9887
  checkbox.tabIndex = -1;
9768
- imageContainer.append(checkbox);
9888
+ checkbox.setAttribute("data-l10n-id", "pdfjs-thumb-page-checkbox1");
9889
+ checkbox.setAttribute("data-l10n-args", this.#getPageL10nArgs());
9890
+ thumbnailContainer.append(checkbox);
9891
+ this.pasteButton = null;
9769
9892
  }
9770
- const image = this.image = document.createElement("img");
9771
- image.classList.add("thumbnailImage", "missingThumbnailImage");
9772
- image.role = "button";
9773
- image.tabIndex = -1;
9774
- image.draggable = false;
9775
9893
  this.#updateDims();
9776
- imageContainer.append(image);
9777
- container.append(imageContainer);
9894
+ container.append(thumbnailContainer);
9895
+ }
9896
+ clone(container, id) {
9897
+ const thumbnailView = new PDFThumbnailView({
9898
+ container,
9899
+ id,
9900
+ eventBus: this.eventBus,
9901
+ defaultViewport: this.viewport,
9902
+ optionalContentConfigPromise: this._optionalContentConfigPromise,
9903
+ linkService: this.linkService,
9904
+ renderingQueue: this.renderingQueue,
9905
+ maxCanvasPixels: this.maxCanvasPixels,
9906
+ maxCanvasDim: this.maxCanvasDim,
9907
+ pageColors: this.pageColors,
9908
+ enableSplitMerge: !!this.checkbox
9909
+ });
9910
+ thumbnailView.setPdfPage(this.pdfPage);
9911
+ const {
9912
+ imageContainer
9913
+ } = this;
9914
+ if (!imageContainer.classList.contains("missingThumbnailImage")) {
9915
+ thumbnailView.image.replaceWith(this.image.cloneNode(true));
9916
+ thumbnailView.imageContainer.classList.remove("missingThumbnailImage");
9917
+ }
9918
+ return thumbnailView;
9919
+ }
9920
+ addPasteButton(pasteCallback) {
9921
+ if (this.pasteButton) {
9922
+ return;
9923
+ }
9924
+ const pasteButton = this.pasteButton = document.createElement("button");
9925
+ pasteButton.classList.add("thumbnailPasteButton", "viewsManagerButton");
9926
+ pasteButton.tabIndex = 0;
9927
+ const span = document.createElement("span");
9928
+ span.setAttribute("data-l10n-id", "pdfjs-views-manager-paste-button-label");
9929
+ pasteButton.append(span);
9930
+ pasteButton.addEventListener("click", () => {
9931
+ pasteCallback(this.id);
9932
+ });
9933
+ this.imageContainer.after(pasteButton);
9934
+ }
9935
+ toggleSelected(isSelected) {
9936
+ if (this.checkbox) {
9937
+ this.checkbox.checked = isSelected;
9938
+ }
9778
9939
  }
9779
9940
  updateId(newId) {
9780
9941
  this.id = newId;
9781
9942
  this.renderingId = `thumbnail${newId}`;
9782
9943
  this.div.setAttribute("page-number", newId);
9944
+ this.imageContainer.setAttribute("page-number", newId);
9783
9945
  this.setPageLabel(this.pageLabel);
9784
9946
  }
9785
9947
  #updateDims() {
@@ -9791,7 +9953,13 @@ class PDFThumbnailView {
9791
9953
  const canvasWidth = this.canvasWidth = THUMBNAIL_WIDTH;
9792
9954
  const canvasHeight = this.canvasHeight = canvasWidth / ratio | 0;
9793
9955
  this.scale = canvasWidth / width;
9794
- this.image.style.height = `${canvasHeight}px`;
9956
+ this.imageContainer.style.height = `${canvasHeight}px`;
9957
+ }
9958
+ get renderingState() {
9959
+ return this.#renderingState;
9960
+ }
9961
+ set renderingState(state) {
9962
+ this.#renderingState = state;
9795
9963
  }
9796
9964
  setPdfPage(pdfPage) {
9797
9965
  this.pdfPage = pdfPage;
@@ -9808,17 +9976,23 @@ class PDFThumbnailView {
9808
9976
  this.renderingState = RenderingStates.INITIAL;
9809
9977
  this.#updateDims();
9810
9978
  const {
9811
- image
9979
+ image,
9980
+ imageContainer
9812
9981
  } = this;
9813
9982
  const url = image.src;
9814
9983
  if (url) {
9815
9984
  URL.revokeObjectURL(url);
9816
- image.removeAttribute("data-l10n-id");
9817
- image.removeAttribute("data-l10n-args");
9818
9985
  image.src = "";
9819
- this.image.classList.add("missingThumbnailImage");
9986
+ imageContainer.removeAttribute("data-l10n-id");
9987
+ imageContainer.removeAttribute("data-l10n-args");
9988
+ imageContainer.classList.add("missingThumbnailImage");
9820
9989
  }
9821
9990
  }
9991
+ destroy() {
9992
+ this.reset();
9993
+ this.toggleCurrent(false);
9994
+ this.div.remove();
9995
+ }
9822
9996
  update({
9823
9997
  rotation = null
9824
9998
  }) {
@@ -9833,12 +10007,21 @@ class PDFThumbnailView {
9833
10007
  this.reset();
9834
10008
  }
9835
10009
  toggleCurrent(isCurrent) {
10010
+ const {
10011
+ imageContainer
10012
+ } = this;
9836
10013
  if (isCurrent) {
9837
- this.image.ariaCurrent = "page";
9838
- this.image.tabIndex = 0;
10014
+ imageContainer.ariaCurrent = "page";
10015
+ imageContainer.tabIndex = 0;
10016
+ if (this.checkbox) {
10017
+ this.checkbox.tabIndex = 0;
10018
+ }
9839
10019
  } else {
9840
- this.image.ariaCurrent = false;
9841
- this.image.tabIndex = -1;
10020
+ imageContainer.ariaCurrent = false;
10021
+ imageContainer.tabIndex = -1;
10022
+ if (this.checkbox) {
10023
+ this.checkbox.tabIndex = -1;
10024
+ }
9842
10025
  }
9843
10026
  }
9844
10027
  cancelRendering() {
@@ -9868,6 +10051,7 @@ class PDFThumbnailView {
9868
10051
  }
9869
10052
  const reducedCanvas = this.#reduceImage(canvas);
9870
10053
  const {
10054
+ imageContainer,
9871
10055
  image
9872
10056
  } = this;
9873
10057
  const {
@@ -9878,8 +10062,8 @@ class PDFThumbnailView {
9878
10062
  const blob = await promise;
9879
10063
  image.src = URL.createObjectURL(blob);
9880
10064
  image.setAttribute("data-l10n-id", "pdfjs-thumb-page-canvas");
9881
- image.setAttribute("data-l10n-args", this.#pageL10nArgs);
9882
- image.classList.remove("missingThumbnailImage");
10065
+ image.setAttribute("data-l10n-args", this.#getPageL10nArgs());
10066
+ imageContainer.classList.remove("missingThumbnailImage");
9883
10067
  if (!FeatureTest.isOffscreenCanvasSupported) {
9884
10068
  reducedCanvas.width = reducedCanvas.height = 0;
9885
10069
  }
@@ -10005,14 +10189,17 @@ class PDFThumbnailView {
10005
10189
  ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height);
10006
10190
  return canvas;
10007
10191
  }
10008
- get #pageL10nArgs() {
10192
+ #getPageL10nArgs(hasTotal = false) {
10009
10193
  return JSON.stringify({
10010
- page: this.pageLabel ?? this.id
10194
+ page: this.pageLabel ?? this.id,
10195
+ total: hasTotal ? this.linkService.pagesCount : undefined
10011
10196
  });
10012
10197
  }
10013
10198
  setPageLabel(label) {
10014
10199
  this.pageLabel = typeof label === "string" ? label : null;
10015
- this.image.setAttribute("data-l10n-args", this.#pageL10nArgs);
10200
+ this.imageContainer.setAttribute("data-l10n-args", this.#getPageL10nArgs(true));
10201
+ this.image.setAttribute("data-l10n-args", this.#getPageL10nArgs());
10202
+ this.checkbox?.setAttribute("data-l10n-args", this.#getPageL10nArgs());
10016
10203
  }
10017
10204
  }
10018
10205
 
@@ -10021,6 +10208,7 @@ class PDFThumbnailView {
10021
10208
 
10022
10209
 
10023
10210
 
10211
+
10024
10212
  const SCROLL_OPTIONS = {
10025
10213
  behavior: "instant",
10026
10214
  block: "nearest",
@@ -10048,8 +10236,17 @@ class PDFThumbnailViewer {
10048
10236
  #pageNumberToRemove = NaN;
10049
10237
  #currentScrollBottom = 0;
10050
10238
  #currentScrollTop = 0;
10051
- #pagesMapper = PagesMapper.instance;
10239
+ #pagesMapper = null;
10052
10240
  #manageSaveAsButton = null;
10241
+ #manageDeleteButton = null;
10242
+ #manageCopyButton = null;
10243
+ #manageCutButton = null;
10244
+ #copiedThumbnails = null;
10245
+ #copiedPageNumbers = null;
10246
+ #isCut = false;
10247
+ #isOneColumnView = false;
10248
+ #scrollableContainerWidth = 0;
10249
+ #scrollableContainerHeight = 0;
10053
10250
  constructor({
10054
10251
  container,
10055
10252
  eventBus,
@@ -10061,7 +10258,8 @@ class PDFThumbnailViewer {
10061
10258
  abortSignal,
10062
10259
  enableHWA,
10063
10260
  enableSplitMerge,
10064
- manageMenu
10261
+ manageMenu,
10262
+ addFileButton
10065
10263
  }) {
10066
10264
  this.scrollableContainer = container.parentElement;
10067
10265
  this.container = container;
@@ -10082,6 +10280,11 @@ class PDFThumbnailViewer {
10082
10280
  delete: del,
10083
10281
  saveAs
10084
10282
  } = manageMenu;
10283
+ this.eventBus.on("pagesloaded", () => {
10284
+ button.disabled = false;
10285
+ }, {
10286
+ once: true
10287
+ });
10085
10288
  this._manageMenu = new Menu(menu, button, [copy, cut, del, saveAs]);
10086
10289
  this.#manageSaveAsButton = saveAs;
10087
10290
  saveAs.addEventListener("click", () => {
@@ -10090,6 +10293,14 @@ class PDFThumbnailViewer {
10090
10293
  data: this.#pagesMapper.getPageMappingForSaving()
10091
10294
  });
10092
10295
  });
10296
+ this.#manageDeleteButton = del;
10297
+ del.addEventListener("click", this.#deletePages.bind(this));
10298
+ this.#manageCopyButton = copy;
10299
+ copy.addEventListener("click", this.#copyPages.bind(this));
10300
+ this.#manageCutButton = cut;
10301
+ cut.addEventListener("click", this.#cutPages.bind(this));
10302
+ this.#toggleMenuEntries(false);
10303
+ button.disabled = true;
10093
10304
  } else {
10094
10305
  manageMenu.button.hidden = true;
10095
10306
  }
@@ -10120,7 +10331,7 @@ class PDFThumbnailViewer {
10120
10331
  }
10121
10332
  if (pageNumber !== this._currentPageNumber) {
10122
10333
  const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1];
10123
- prevThumbnailView.toggleCurrent(false);
10334
+ prevThumbnailView?.toggleCurrent(false);
10124
10335
  thumbnailView.toggleCurrent(true);
10125
10336
  this._currentPageNumber = pageNumber;
10126
10337
  }
@@ -10131,15 +10342,14 @@ class PDFThumbnailViewer {
10131
10342
  } = this.#getVisibleThumbs();
10132
10343
  if (views.length > 0) {
10133
10344
  let shouldScroll = false;
10134
- if (pageNumber <= this.#pagesMapper.getPageNumber(first.id) || pageNumber >= this.#pagesMapper.getPageNumber(last.id)) {
10345
+ if (pageNumber <= first.id || pageNumber >= last.id) {
10135
10346
  shouldScroll = true;
10136
10347
  } else {
10137
10348
  for (const {
10138
10349
  id,
10139
10350
  percent
10140
10351
  } of views) {
10141
- const mappedPageNumber = this.#pagesMapper.getPageNumber(id);
10142
- if (mappedPageNumber !== pageNumber) {
10352
+ if (id !== pageNumber) {
10143
10353
  continue;
10144
10354
  }
10145
10355
  shouldScroll = percent < 100;
@@ -10196,6 +10406,7 @@ class PDFThumbnailViewer {
10196
10406
  if (!pdfDocument) {
10197
10407
  return;
10198
10408
  }
10409
+ this.#pagesMapper = pdfDocument.pagesMapper;
10199
10410
  const firstPagePromise = pdfDocument.getPage(1);
10200
10411
  const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
10201
10412
  intent: "display"
@@ -10290,24 +10501,45 @@ class PDFThumbnailViewer {
10290
10501
  static #getScaleFactor(image) {
10291
10502
  return PDFThumbnailViewer.#draggingScaleFactor ||= parseFloat(getComputedStyle(image).getPropertyValue("--thumbnail-dragging-scale"));
10292
10503
  }
10293
- #updateThumbnails() {
10504
+ #updateThumbnails(currentPageNumber) {
10505
+ let newCurrentPageNumber = 0;
10294
10506
  const pagesMapper = this.#pagesMapper;
10295
10507
  this.container.replaceChildren();
10296
10508
  const prevThumbnails = this._thumbnails;
10297
10509
  const newThumbnails = this._thumbnails = [];
10298
10510
  const fragment = document.createDocumentFragment();
10299
- for (let i = 0, ii = pagesMapper.pagesNumber; i < ii; i++) {
10300
- const prevPageIndex = pagesMapper.getPrevPageNumber(i + 1) - 1;
10301
- if (prevPageIndex === -1) {
10511
+ const isCut = this.#isCut;
10512
+ const oldThumbnails = new Set(prevThumbnails);
10513
+ for (let i = 1, ii = pagesMapper.pagesNumber; i <= ii; i++) {
10514
+ const prevPageNumber = pagesMapper.getPrevPageNumber(i);
10515
+ if (prevPageNumber < 0) {
10516
+ let thumbnail = this.#copiedThumbnails.get(-prevPageNumber);
10517
+ oldThumbnails.delete(thumbnail);
10518
+ thumbnail.checkbox.checked = false;
10519
+ if (isCut) {
10520
+ thumbnail.updateId(i);
10521
+ fragment.append(thumbnail.div);
10522
+ } else {
10523
+ thumbnail = thumbnail.clone(fragment, i);
10524
+ }
10525
+ newThumbnails.push(thumbnail);
10302
10526
  continue;
10303
10527
  }
10304
- const newThumbnail = prevThumbnails[prevPageIndex];
10528
+ if (prevPageNumber === currentPageNumber) {
10529
+ newCurrentPageNumber = i;
10530
+ }
10531
+ const newThumbnail = prevThumbnails[prevPageNumber - 1];
10305
10532
  newThumbnails.push(newThumbnail);
10306
- newThumbnail.updateId(i + 1);
10533
+ newThumbnail.updateId(i);
10534
+ oldThumbnails.delete(newThumbnail);
10307
10535
  newThumbnail.checkbox.checked = false;
10308
10536
  fragment.append(newThumbnail.div);
10309
10537
  }
10310
10538
  this.container.append(fragment);
10539
+ for (const oldThumbnail of oldThumbnails) {
10540
+ oldThumbnail.destroy();
10541
+ }
10542
+ return newCurrentPageNumber;
10311
10543
  }
10312
10544
  #onStartDragging(draggedThumbnail) {
10313
10545
  this.#currentScrollTop = this.scrollableContainer.scrollTop;
@@ -10323,29 +10555,29 @@ class PDFThumbnailViewer {
10323
10555
  for (const selected of this.#selectedPages) {
10324
10556
  const thumbnail = this._thumbnails[selected - 1];
10325
10557
  const placeholder = thumbnail.placeholder = document.createElement("div");
10326
- placeholder.classList.add("thumbnailImage", "placeholder");
10558
+ placeholder.classList.add("thumbnailImageContainer", "placeholder");
10327
10559
  const {
10328
10560
  div,
10329
- image
10561
+ imageContainer
10330
10562
  } = thumbnail;
10331
10563
  div.classList.add("isDragging");
10332
- placeholder.style.height = getComputedStyle(image).height;
10333
- image.after(placeholder);
10564
+ placeholder.style.height = getComputedStyle(imageContainer).height;
10565
+ imageContainer.after(placeholder);
10334
10566
  if (selected !== startPageNumber) {
10335
- image.classList.add("hidden");
10567
+ imageContainer.classList.add("hidden");
10336
10568
  continue;
10337
10569
  }
10338
10570
  if (this.#selectedPages.size === 1) {
10339
- image.classList.add("draggingThumbnail");
10340
- this.#draggedContainer = image;
10571
+ imageContainer.classList.add("draggingThumbnail");
10572
+ this.#draggedContainer = imageContainer;
10341
10573
  continue;
10342
10574
  }
10343
10575
  const draggedContainer = this.#draggedContainer = document.createElement("div");
10344
- draggedContainer.classList.add("draggingThumbnail", "thumbnailImage", "multiple");
10345
- draggedContainer.style.height = getComputedStyle(image).height;
10346
- image.replaceWith(draggedContainer);
10347
- image.classList.remove("thumbnailImage");
10348
- draggedContainer.append(image);
10576
+ draggedContainer.classList.add("draggingThumbnail", "thumbnailImageContainer", "multiple");
10577
+ draggedContainer.style.height = getComputedStyle(imageContainer).height;
10578
+ imageContainer.replaceWith(draggedContainer);
10579
+ imageContainer.classList.remove("thumbnailImageContainer");
10580
+ draggedContainer.append(imageContainer);
10349
10581
  draggedContainer.setAttribute("data-multiple-count", this.#selectedPages.size);
10350
10582
  }
10351
10583
  }
@@ -10364,48 +10596,41 @@ class PDFThumbnailViewer {
10364
10596
  const {
10365
10597
  div,
10366
10598
  placeholder,
10367
- image
10599
+ imageContainer
10368
10600
  } = thumbnail;
10369
10601
  placeholder.remove();
10370
- image.classList.remove("draggingThumbnail", "hidden");
10602
+ imageContainer.classList.remove("draggingThumbnail", "hidden");
10371
10603
  div.classList.remove("isDragging");
10372
10604
  }
10373
10605
  if (draggedContainer.classList.contains("multiple")) {
10374
- const originalImage = draggedContainer.firstElementChild;
10375
- draggedContainer.replaceWith(originalImage);
10376
- originalImage.classList.add("thumbnailImage");
10606
+ const originalImageContainer = draggedContainer.firstElementChild;
10607
+ draggedContainer.replaceWith(originalImageContainer);
10608
+ originalImageContainer.classList.add("thumbnailImageContainer");
10377
10609
  } else {
10378
10610
  draggedContainer.style.translate = "";
10379
10611
  }
10380
10612
  const selectedPages = this.#selectedPages;
10381
10613
  if (!isNaN(lastDraggedOverIndex) && isDropping && !(selectedPages.size === 1 && (selectedPages.has(lastDraggedOverIndex + 1) || selectedPages.has(lastDraggedOverIndex + 2)))) {
10614
+ this._thumbnails[this._currentPageNumber - 1]?.toggleCurrent(false);
10615
+ this._currentPageNumber = -1;
10382
10616
  const newIndex = lastDraggedOverIndex + 1;
10383
10617
  const pagesToMove = Array.from(selectedPages).sort((a, b) => a - b);
10384
10618
  const pagesMapper = this.#pagesMapper;
10385
- const currentPageId = pagesMapper.getPageId(this._currentPageNumber);
10386
- const newCurrentPageId = pagesMapper.getPageId(isNaN(this.#pageNumberToRemove) ? pagesToMove[0] : this.#pageNumberToRemove);
10387
- this.eventBus.dispatch("beforepagesedited", {
10388
- source: this,
10389
- pagesMapper
10390
- });
10619
+ let currentPageNumber = isNaN(this.#pageNumberToRemove) ? pagesToMove[0] : this.#pageNumberToRemove;
10391
10620
  pagesMapper.movePages(selectedPages, pagesToMove, newIndex);
10392
- this.#updateThumbnails();
10393
- this._currentPageNumber = pagesMapper.getPageNumber(currentPageId);
10621
+ currentPageNumber = this.#updateThumbnails(currentPageNumber);
10394
10622
  this.#computeThumbnailsPosition();
10395
10623
  selectedPages.clear();
10396
10624
  this.#pageNumberToRemove = NaN;
10397
- const isIdentity = this.#manageSaveAsButton.disabled = !this.#pagesMapper.hasBeenAltered();
10398
- if (!isIdentity) {
10399
- this.eventBus.dispatch("pagesedited", {
10400
- source: this,
10401
- pagesMapper,
10402
- index: newIndex,
10403
- pagesToMove
10404
- });
10405
- }
10406
- const newCurrentPageNumber = pagesMapper.getPageNumber(newCurrentPageId);
10625
+ this.#updateMenuEntries();
10626
+ this.eventBus.dispatch("pagesedited", {
10627
+ source: this,
10628
+ pagesMapper,
10629
+ type: "move"
10630
+ });
10407
10631
  setTimeout(() => {
10408
- this.linkService.goToPage(newCurrentPageNumber);
10632
+ this.forceRendering();
10633
+ this.linkService.goToPage(currentPageNumber);
10409
10634
  }, 0);
10410
10635
  }
10411
10636
  if (!isNaN(this.#pageNumberToRemove)) {
@@ -10413,14 +10638,108 @@ class PDFThumbnailViewer {
10413
10638
  this.#pageNumberToRemove = NaN;
10414
10639
  }
10415
10640
  }
10641
+ #clearSelection() {
10642
+ for (const pageNumber of this.#selectedPages) {
10643
+ this._thumbnails[pageNumber - 1].toggleSelected(false);
10644
+ }
10645
+ this.#selectedPages.clear();
10646
+ }
10647
+ #copyPages(clearSelection = true) {
10648
+ const pageNumbersToCopy = this.#copiedPageNumbers = Uint32Array.from(this.#selectedPages).sort((a, b) => a - b);
10649
+ const pagesMapper = this.#pagesMapper;
10650
+ pagesMapper.copyPages(pageNumbersToCopy);
10651
+ this.#copiedThumbnails ||= new Map();
10652
+ for (const pageNumber of pageNumbersToCopy) {
10653
+ this.#copiedThumbnails.set(pageNumber, this._thumbnails[pageNumber - 1]);
10654
+ }
10655
+ this.eventBus.dispatch("pagesedited", {
10656
+ source: this,
10657
+ pagesMapper,
10658
+ pageNumbers: pageNumbersToCopy,
10659
+ type: "copy"
10660
+ });
10661
+ if (clearSelection) {
10662
+ this.#clearSelection();
10663
+ }
10664
+ for (const thumbnail of this._thumbnails) {
10665
+ thumbnail.addPasteButton(this.#pastePages.bind(this));
10666
+ }
10667
+ this.container.classList.add("pasteMode");
10668
+ this.#toggleMenuEntries(false);
10669
+ }
10670
+ #cutPages() {
10671
+ this.#isCut = true;
10672
+ this.#copyPages(false);
10673
+ this.#deletePages("cut");
10674
+ }
10675
+ #pastePages(index) {
10676
+ this.container.classList.remove("pasteMode");
10677
+ this.#toggleMenuEntries(true);
10678
+ const pagesMapper = this.#pagesMapper;
10679
+ let currentPageNumber = this.#copiedPageNumbers.includes(this._currentPageNumber) ? 0 : this._currentPageNumber;
10680
+ pagesMapper.pastePages(index);
10681
+ currentPageNumber = this.#updateThumbnails(currentPageNumber);
10682
+ this.eventBus.dispatch("pagesedited", {
10683
+ source: this,
10684
+ pagesMapper,
10685
+ hasBeenCut: this.#isCut,
10686
+ type: "paste"
10687
+ });
10688
+ this.#copiedThumbnails = null;
10689
+ this.#isCut = false;
10690
+ this.#updateMenuEntries();
10691
+ setTimeout(() => {
10692
+ this.forceRendering();
10693
+ this.linkService.goToPage(currentPageNumber || 1);
10694
+ }, 0);
10695
+ }
10696
+ #deletePages(type = "delete") {
10697
+ const selectedPages = this.#selectedPages;
10698
+ if (selectedPages.size === 0) {
10699
+ return;
10700
+ }
10701
+ const pagesMapper = this.#pagesMapper;
10702
+ let currentPageNumber = selectedPages.has(this._currentPageNumber) ? 0 : this._currentPageNumber;
10703
+ const pagesToDelete = Uint32Array.from(selectedPages).sort((a, b) => a - b);
10704
+ pagesMapper.deletePages(pagesToDelete);
10705
+ currentPageNumber = this.#updateThumbnails(currentPageNumber);
10706
+ selectedPages.clear();
10707
+ this.#updateMenuEntries();
10708
+ this.eventBus.dispatch("pagesedited", {
10709
+ source: this,
10710
+ pagesMapper,
10711
+ pageNumbers: pagesToDelete,
10712
+ type
10713
+ });
10714
+ setTimeout(() => {
10715
+ this.forceRendering();
10716
+ this.linkService.goToPage(currentPageNumber || 1);
10717
+ }, 0);
10718
+ }
10719
+ #updateMenuEntries() {
10720
+ this.#manageSaveAsButton.disabled = !this.#pagesMapper.hasBeenAltered();
10721
+ this.#manageDeleteButton.disabled = this.#manageCopyButton.disabled = this.#manageCutButton.disabled = !this.#selectedPages?.size;
10722
+ }
10723
+ #toggleMenuEntries(enable) {
10724
+ this.#manageSaveAsButton.disabled = this.#manageDeleteButton.disabled = this.#manageCopyButton.disabled = this.#manageCutButton.disabled = !enable;
10725
+ }
10416
10726
  #moveDraggedContainer(dx, dy) {
10417
- this.#draggedImageOffsetX += dx;
10418
- this.#draggedImageOffsetY += dy;
10727
+ if (this.#isOneColumnView) {
10728
+ dx = 0;
10729
+ }
10730
+ if (this.#draggedImageX + dx < 0 || this.#draggedImageX + this.#draggedImageWidth + dx > this.#scrollableContainerWidth) {
10731
+ dx = 0;
10732
+ }
10733
+ if (this.#draggedImageY + dy < 0 || this.#draggedImageY + this.#draggedImageHeight + dy > this.#scrollableContainerHeight) {
10734
+ dy = 0;
10735
+ }
10419
10736
  this.#draggedImageX += dx;
10420
10737
  this.#draggedImageY += dy;
10738
+ this.#draggedImageOffsetX += dx;
10739
+ this.#draggedImageOffsetY += dy;
10421
10740
  this.#draggedContainer.style.translate = `${this.#draggedImageOffsetX}px ${this.#draggedImageOffsetY}px`;
10422
10741
  if (this.#draggedImageY + this.#draggedImageHeight > this.#currentScrollBottom) {
10423
- this.scrollableContainer.scrollTop = Math.min(this.scrollableContainer.scrollTop + PIXELS_TO_SCROLL_WHEN_DRAGGING, this.scrollableContainer.scrollHeight);
10742
+ this.scrollableContainer.scrollTop = Math.min(this.scrollableContainer.scrollTop + PIXELS_TO_SCROLL_WHEN_DRAGGING, this.#scrollableContainerHeight);
10424
10743
  } else if (this.#draggedImageY < this.#currentScrollTop) {
10425
10744
  this.scrollableContainer.scrollTop = Math.max(this.scrollableContainer.scrollTop - PIXELS_TO_SCROLL_WHEN_DRAGGING, 0);
10426
10745
  }
@@ -10520,6 +10839,11 @@ class PDFThumbnailViewer {
10520
10839
  lastSpace: (positionsLastX.at(-1) - lastRightX) / 2,
10521
10840
  bbox
10522
10841
  };
10842
+ this.#isOneColumnView = positionsX.length === 1;
10843
+ ({
10844
+ clientWidth: this.#scrollableContainerWidth,
10845
+ scrollHeight: this.#scrollableContainerHeight
10846
+ } = this.scrollableContainer);
10523
10847
  }
10524
10848
  #addEventListeners() {
10525
10849
  this.eventBus.on("resize", ({
@@ -10530,34 +10854,59 @@ class PDFThumbnailViewer {
10530
10854
  }
10531
10855
  });
10532
10856
  this.container.addEventListener("keydown", e => {
10857
+ const {
10858
+ target
10859
+ } = e;
10860
+ const isCheckbox = target instanceof HTMLInputElement && target.type === "checkbox";
10533
10861
  switch (e.key) {
10534
10862
  case "ArrowLeft":
10535
- this.#goToNextItem(e.target, false, true);
10863
+ this.#goToNextItem(target, false, true, isCheckbox);
10536
10864
  stopEvent(e);
10537
10865
  break;
10538
10866
  case "ArrowRight":
10539
- this.#goToNextItem(e.target, true, true);
10867
+ this.#goToNextItem(target, true, true, isCheckbox);
10540
10868
  stopEvent(e);
10541
10869
  break;
10542
10870
  case "ArrowDown":
10543
- this.#goToNextItem(e.target, true, false);
10871
+ this.#goToNextItem(target, true, false, isCheckbox);
10544
10872
  stopEvent(e);
10545
10873
  break;
10546
10874
  case "ArrowUp":
10547
- this.#goToNextItem(e.target, false, false);
10875
+ this.#goToNextItem(target, false, false, isCheckbox);
10548
10876
  stopEvent(e);
10549
10877
  break;
10550
10878
  case "Home":
10551
- this._thumbnails[0].image.focus();
10879
+ this.#focusThumbnailElement(this._thumbnails[0], isCheckbox);
10552
10880
  stopEvent(e);
10553
10881
  break;
10554
10882
  case "End":
10555
- this._thumbnails.at(-1).image.focus();
10883
+ this.#focusThumbnailElement(this._thumbnails.at(-1), isCheckbox);
10556
10884
  stopEvent(e);
10557
10885
  break;
10558
10886
  case "Enter":
10559
10887
  case " ":
10560
- this.#goToPage(e);
10888
+ if (!isCheckbox) {
10889
+ this.#goToPage(e);
10890
+ }
10891
+ break;
10892
+ case "c":
10893
+ if (this.#enableSplitMerge && (e.ctrlKey || e.metaKey) && this.#selectedPages?.size) {
10894
+ this.#copyPages();
10895
+ stopEvent(e);
10896
+ }
10897
+ break;
10898
+ case "x":
10899
+ if (this.#enableSplitMerge && (e.ctrlKey || e.metaKey) && this.#selectedPages?.size) {
10900
+ this.#cutPages();
10901
+ stopEvent(e);
10902
+ }
10903
+ break;
10904
+ case "Delete":
10905
+ case "Backspace":
10906
+ if (this.#enableSplitMerge && this.#selectedPages?.size) {
10907
+ this.#deletePages();
10908
+ stopEvent(e);
10909
+ }
10561
10910
  break;
10562
10911
  }
10563
10912
  });
@@ -10581,6 +10930,7 @@ class PDFThumbnailViewer {
10581
10930
  } else {
10582
10931
  set.delete(pageNumber);
10583
10932
  }
10933
+ this.#updateMenuEntries();
10584
10934
  }
10585
10935
  #addDragListeners() {
10586
10936
  if (!this.#enableSplitMerge) {
@@ -10593,7 +10943,7 @@ class PDFThumbnailViewer {
10593
10943
  clientY: clickY,
10594
10944
  pointerId: dragPointerId
10595
10945
  } = e;
10596
- if (!isNaN(this.#lastDraggedOverIndex) || !draggedImage.classList.contains("thumbnailImage")) {
10946
+ if (e.button !== 0 || this.#pagesMapper.copiedPageNumbers?.length > 0 || !isNaN(this.#lastDraggedOverIndex) || !draggedImage.classList.contains("thumbnailImageContainer")) {
10597
10947
  return;
10598
10948
  }
10599
10949
  const thumbnail = draggedImage.parentElement;
@@ -10605,8 +10955,12 @@ class PDFThumbnailViewer {
10605
10955
  let prevDragY = clickY;
10606
10956
  let prevScrollTop = this.scrollableContainer.scrollTop;
10607
10957
  const scaleFactor = PDFThumbnailViewer.#getScaleFactor(draggedImage);
10608
- this.#draggedImageOffsetX = ((scaleFactor - 1) * e.layerX + draggedImage.offsetLeft) / scaleFactor;
10609
10958
  this.#draggedImageOffsetY = ((scaleFactor - 1) * e.layerY + draggedImage.offsetTop) / scaleFactor;
10959
+ if (this.#isOneColumnView) {
10960
+ this.#draggedImageOffsetX = draggedImage.offsetLeft + (scaleFactor - 1) * 0.5 * draggedImage.offsetWidth / scaleFactor;
10961
+ } else {
10962
+ this.#draggedImageOffsetX = ((scaleFactor - 1) * e.layerX + draggedImage.offsetLeft) / scaleFactor;
10963
+ }
10610
10964
  this.#draggedImageX = thumbnail.offsetLeft + this.#draggedImageOffsetX;
10611
10965
  this.#draggedImageY = thumbnail.offsetTop + this.#draggedImageOffsetY;
10612
10966
  this.#draggedImageWidth = draggedImage.offsetWidth / scaleFactor;
@@ -10617,10 +10971,10 @@ class PDFThumbnailViewer {
10617
10971
  clientY: y,
10618
10972
  pointerId
10619
10973
  } = ev;
10620
- if (pointerId !== dragPointerId || Math.abs(x - clickX) <= DRAG_THRESHOLD_IN_PIXELS && Math.abs(y - clickY) <= DRAG_THRESHOLD_IN_PIXELS) {
10621
- return;
10622
- }
10623
10974
  if (isNaN(this.#lastDraggedOverIndex)) {
10975
+ if (pointerId !== dragPointerId || Math.abs(x - clickX) <= DRAG_THRESHOLD_IN_PIXELS && Math.abs(y - clickY) <= DRAG_THRESHOLD_IN_PIXELS) {
10976
+ return;
10977
+ }
10624
10978
  this.#onStartDragging(thumbnail);
10625
10979
  const stopDragging = (_e, isDropping = false) => {
10626
10980
  this.#onStopDragging(isDropping);
@@ -10676,6 +11030,13 @@ class PDFThumbnailViewer {
10676
11030
  passive: false,
10677
11031
  signal
10678
11032
  });
11033
+ window.addEventListener("keydown", kEv => {
11034
+ if (kEv.key === "Escape" && !isNaN(this.#lastDraggedOverIndex)) {
11035
+ stopDragging(kEv);
11036
+ }
11037
+ }, {
11038
+ signal
11039
+ });
10679
11040
  }
10680
11041
  const dx = x - prevDragX;
10681
11042
  const dy = y - prevDragY;
@@ -10706,13 +11067,20 @@ class PDFThumbnailViewer {
10706
11067
  const {
10707
11068
  target
10708
11069
  } = e;
10709
- if (target.classList.contains("thumbnailImage")) {
11070
+ if (target.classList.contains("thumbnailImageContainer")) {
10710
11071
  const pageNumber = parseInt(target.parentElement.getAttribute("page-number"), 10);
10711
11072
  this.linkService.goToPage(pageNumber);
10712
11073
  stopEvent(e);
10713
11074
  }
10714
11075
  }
10715
- #goToNextItem(element, forward, horizontal) {
11076
+ #focusThumbnailElement(thumbnail, focusCheckbox) {
11077
+ if (focusCheckbox && thumbnail.checkbox) {
11078
+ thumbnail.checkbox.focus();
11079
+ } else {
11080
+ thumbnail.imageContainer.focus();
11081
+ }
11082
+ }
11083
+ #goToNextItem(element, forward, horizontal, navigateCheckboxes = false) {
10716
11084
  let currentPageNumber = parseInt(element.parentElement.getAttribute("page-number"), 10);
10717
11085
  if (isNaN(currentPageNumber)) {
10718
11086
  currentPageNumber = this._currentPageNumber;
@@ -10748,7 +11116,7 @@ class PDFThumbnailViewer {
10748
11116
  }
10749
11117
  }
10750
11118
  if (nextThumbnail) {
10751
- nextThumbnail.image.focus();
11119
+ this.#focusThumbnailElement(nextThumbnail, navigateCheckboxes);
10752
11120
  }
10753
11121
  }
10754
11122
  #findClosestThumbnail(x, y) {
@@ -10769,16 +11137,28 @@ class PDFThumbnailViewer {
10769
11137
  if (positionsY[yPos] <= y && y < (positionsY[yPos + 1] ?? Infinity) && xArray[xPos] <= x && x < (xArray[xPos + 1] ?? Infinity)) {
10770
11138
  return null;
10771
11139
  }
10772
- yPos = binarySearchFirstItem(positionsY, cy => y < cy) - 1;
10773
- xArray = yPos === positionsY.length - 1 && positionsLastX.length > 0 ? positionsLastX : positionsX;
10774
- xPos = Math.max(0, binarySearchFirstItem(xArray, cx => x < cx) - 1);
10775
- if (yPos < 0) {
10776
- if (xPos <= 0) {
10777
- xPos = -1;
11140
+ let index;
11141
+ yPos = binarySearchFirstItem(positionsY, cy => y < cy);
11142
+ if (this.#isOneColumnView) {
11143
+ index = yPos - 1;
11144
+ } else {
11145
+ if (yPos === positionsY.length) {
11146
+ yPos = positionsY.length - 1;
11147
+ } else {
11148
+ const dist1 = Math.abs(positionsY[yPos - 1] - y);
11149
+ const dist2 = Math.abs(positionsY[yPos] - y);
11150
+ yPos = dist1 < dist2 ? yPos - 1 : yPos;
11151
+ }
11152
+ xArray = yPos === positionsY.length - 1 && positionsLastX.length > 0 ? positionsLastX : positionsX;
11153
+ xPos = binarySearchFirstItem(xArray, cx => x < cx) - 1;
11154
+ if (yPos < 0) {
11155
+ if (xPos <= 0) {
11156
+ xPos = -1;
11157
+ }
11158
+ yPos = 0;
10778
11159
  }
10779
- yPos = 0;
11160
+ index = MathClamp(yPos * positionsX.length + xPos, -1, this._thumbnails.length - 1);
10780
11161
  }
10781
- const index = MathClamp(yPos * positionsX.length + xPos, -1, this._thumbnails.length - 1);
10782
11162
  if (index === lastDraggedOverIndex) {
10783
11163
  return null;
10784
11164
  }
@@ -10798,8 +11178,9 @@ class AnnotationEditorLayerBuilder {
10798
11178
  #structTreeLayer = null;
10799
11179
  #textLayer = null;
10800
11180
  #uiManager;
11181
+ #clonedFrom = null;
10801
11182
  constructor(options) {
10802
- this.pdfPage = options.pdfPage;
11183
+ this.pageIndex = options.pageIndex;
10803
11184
  this.accessibilityManager = options.accessibilityManager;
10804
11185
  this.l10n = options.l10n;
10805
11186
  this.l10n ||= new genericl10n_GenericL10n();
@@ -10812,6 +11193,11 @@ class AnnotationEditorLayerBuilder {
10812
11193
  this.#drawLayer = options.drawLayer || null;
10813
11194
  this.#onAppend = options.onAppend || null;
10814
11195
  this.#structTreeLayer = options.structTreeLayer || null;
11196
+ this.#clonedFrom = options.clonedFrom || null;
11197
+ }
11198
+ updatePageIndex(newPageIndex) {
11199
+ this.pageIndex = newPageIndex;
11200
+ this.annotationEditorLayer?.updatePageIndex(newPageIndex);
10815
11201
  }
10816
11202
  async render({
10817
11203
  viewport,
@@ -10843,13 +11229,15 @@ class AnnotationEditorLayerBuilder {
10843
11229
  div,
10844
11230
  structTreeLayer: this.#structTreeLayer,
10845
11231
  accessibilityManager: this.accessibilityManager,
10846
- pageIndex: this.pdfPage.pageNumber - 1,
11232
+ pageIndex: this.pageIndex,
10847
11233
  l10n: this.l10n,
10848
11234
  viewport: clonedViewport,
10849
11235
  annotationLayer: this.#annotationLayer,
10850
11236
  textLayer: this.#textLayer,
10851
11237
  drawLayer: this.#drawLayer
10852
11238
  });
11239
+ this.annotationEditorLayer.setClonedFrom(this.#clonedFrom?.annotationEditorLayer);
11240
+ this.#clonedFrom = null;
10853
11241
  const parameters = {
10854
11242
  viewport: clonedViewport,
10855
11243
  div,
@@ -11246,9 +11634,8 @@ class Autolinker {
11246
11634
  ;// ./web/base_pdf_page_view.js
11247
11635
 
11248
11636
 
11249
- class BasePDFPageView {
11637
+ class BasePDFPageView extends RenderableView {
11250
11638
  #loadingId = null;
11251
- #minDurationToUpdateCanvas = 0;
11252
11639
  #renderError = null;
11253
11640
  #renderingState = RenderingStates.INITIAL;
11254
11641
  #showCanvas = null;
@@ -11262,15 +11649,14 @@ class BasePDFPageView {
11262
11649
  pageColors = null;
11263
11650
  recordedBBoxes = null;
11264
11651
  renderingQueue = null;
11265
- renderTask = null;
11266
- resume = null;
11267
11652
  constructor(options) {
11653
+ super();
11268
11654
  this.eventBus = options.eventBus;
11269
11655
  this.id = options.id;
11270
11656
  this.pageColors = options.pageColors || null;
11271
11657
  this.renderingQueue = options.renderingQueue;
11272
11658
  this.enableOptimizedPartialRendering = options.enableOptimizedPartialRendering ?? false;
11273
- this.#minDurationToUpdateCanvas = options.minDurationToUpdateCanvas ?? 500;
11659
+ this.minDurationToUpdateCanvas = options.minDurationToUpdateCanvas ?? 500;
11274
11660
  }
11275
11661
  get renderingState() {
11276
11662
  return this.#renderingState;
@@ -11316,8 +11702,8 @@ class BasePDFPageView {
11316
11702
  this.#showCanvas = isLastShow => {
11317
11703
  if (updateOnFirstShow) {
11318
11704
  let tempCanvas = this.#tempCanvas;
11319
- if (!isLastShow && this.#minDurationToUpdateCanvas > 0) {
11320
- if (Date.now() - this.#startTime < this.#minDurationToUpdateCanvas) {
11705
+ if (!isLastShow && this.minDurationToUpdateCanvas > 0) {
11706
+ if (Date.now() - this.#startTime < this.minDurationToUpdateCanvas) {
11321
11707
  return;
11322
11708
  }
11323
11709
  if (!tempCanvas) {
@@ -11500,9 +11886,9 @@ class PDFPageDetailView extends BasePDFPageView {
11500
11886
  get renderingState() {
11501
11887
  return super.renderingState;
11502
11888
  }
11503
- set renderingState(value) {
11889
+ set renderingState(state) {
11504
11890
  this.renderingCancelled = false;
11505
- super.renderingState = value;
11891
+ super.renderingState = state;
11506
11892
  }
11507
11893
  reset({
11508
11894
  keepCanvas = false
@@ -11723,8 +12109,8 @@ const PDF_ROLE_TO_HTML_ROLE = {
11723
12109
  TR: "row",
11724
12110
  TH: "columnheader",
11725
12111
  TD: "cell",
11726
- THead: "columnheader",
11727
- TBody: null,
12112
+ THead: "rowgroup",
12113
+ TBody: "rowgroup",
11728
12114
  TFoot: null,
11729
12115
  Caption: null,
11730
12116
  Figure: "figure",
@@ -11811,12 +12197,7 @@ class StructTreeLayerBuilder {
11811
12197
  const label = removeNullCharacters(alt);
11812
12198
  for (const child of structElement.children) {
11813
12199
  if (child.type === "annotation") {
11814
- let attrs = this.#elementAttributes.get(child.id);
11815
- if (!attrs) {
11816
- attrs = new Map();
11817
- this.#elementAttributes.set(child.id, attrs);
11818
- }
11819
- attrs.set("aria-label", label);
12200
+ this.#elementAttributes.getOrInsertComputed(child.id, makeMap).set("aria-label", label);
11820
12201
  added = true;
11821
12202
  }
11822
12203
  }
@@ -11905,7 +12286,7 @@ class StructTreeLayerBuilder {
11905
12286
  this.#elementsToStealFromTextLayer = null;
11906
12287
  }
11907
12288
  }
11908
- #walk(node) {
12289
+ #walk(node, parentNodes = []) {
11909
12290
  if (!node) {
11910
12291
  return null;
11911
12292
  }
@@ -11934,7 +12315,7 @@ class StructTreeLayerBuilder {
11934
12315
  element.setAttribute("role", "heading");
11935
12316
  element.setAttribute("aria-level", match[1]);
11936
12317
  } else if (PDF_ROLE_TO_HTML_ROLE[role]) {
11937
- element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]);
12318
+ element.setAttribute("role", role === "TH" && parentNodes.at(-1)?.role === "TR" && parentNodes.at(-2)?.role === "TBody" ? "rowheader" : PDF_ROLE_TO_HTML_ROLE[role]);
11938
12319
  }
11939
12320
  if (role === "Figure" && this.#addImageInTextLayer(node, element)) {
11940
12321
  return element;
@@ -11966,9 +12347,11 @@ class StructTreeLayerBuilder {
11966
12347
  if (node.children.length === 1 && "id" in node.children[0]) {
11967
12348
  this.#setAttributes(node.children[0], element);
11968
12349
  } else {
12350
+ parentNodes.push(node);
11969
12351
  for (const kid of node.children) {
11970
- element.append(this.#walk(kid));
12352
+ element.append(this.#walk(kid, parentNodes));
11971
12353
  }
12354
+ parentNodes.pop();
11972
12355
  }
11973
12356
  }
11974
12357
  return element;
@@ -12531,6 +12914,9 @@ class TextLayerBuilder {
12531
12914
  if (anchor.nodeType === Node.TEXT_NODE) {
12532
12915
  anchor = anchor.parentNode;
12533
12916
  }
12917
+ if (anchor.classList?.contains("highlight")) {
12918
+ anchor = anchor.parentNode;
12919
+ }
12534
12920
  if (!modifyStart && range.endOffset === 0) {
12535
12921
  do {
12536
12922
  while (!anchor.previousSibling) {
@@ -12571,6 +12957,7 @@ class TextLayerBuilder {
12571
12957
 
12572
12958
 
12573
12959
 
12960
+
12574
12961
  const DEFAULT_LAYER_PROPERTIES = null;
12575
12962
  const LAYERS_ORDER = new Map([["canvasWrapper", 0], ["textLayer", 1], ["annotationLayer", 2], ["annotationEditorLayer", 3], ["xfaLayer", 3]]);
12576
12963
  class PDFPageView extends BasePDFPageView {
@@ -12594,10 +12981,13 @@ class PDFPageView extends BasePDFPageView {
12594
12981
  regularAnnotations: true
12595
12982
  };
12596
12983
  #layers = [null, null, null, null];
12984
+ #clonedFrom = null;
12597
12985
  constructor(options) {
12598
12986
  super(options);
12599
- const container = options.container;
12600
- const defaultViewport = options.defaultViewport;
12987
+ const {
12988
+ container,
12989
+ defaultViewport
12990
+ } = options;
12601
12991
  this.renderingId = "page" + this.id;
12602
12992
  this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES;
12603
12993
  this.pdfPage = null;
@@ -12616,6 +13006,7 @@ class PDFPageView extends BasePDFPageView {
12616
13006
  this.capCanvasAreaFactor = options.capCanvasAreaFactor ?? AppOptions.get("capCanvasAreaFactor");
12617
13007
  this.#enableAutoLinking = options.enableAutoLinking !== false;
12618
13008
  this.#commentManager = options.commentManager || null;
13009
+ this.#clonedFrom = options.clonedFrom || null;
12619
13010
  this.l10n = options.l10n;
12620
13011
  this.l10n ||= new genericl10n_GenericL10n();
12621
13012
  this._isStandalone = !this.renderingQueue?.hasViewer();
@@ -12660,6 +13051,34 @@ class PDFPageView extends BasePDFPageView {
12660
13051
  }
12661
13052
  }
12662
13053
  }
13054
+ clone(id) {
13055
+ const clone = new PDFPageView({
13056
+ container: null,
13057
+ eventBus: this.eventBus,
13058
+ pagesColors: this.pageColors,
13059
+ renderingQueue: this.renderingQueue,
13060
+ enableOptimizedPartialRendering: this.enableOptimizedPartialRendering,
13061
+ minDurationToUpdateCanvas: this.minDurationToUpdateCanvas,
13062
+ defaultViewport: this.viewport,
13063
+ id,
13064
+ layerProperties: this.#layerProperties,
13065
+ scale: this.scale,
13066
+ optionalContentConfigPromise: this._optionalContentConfigPromise,
13067
+ textLayerMode: this.#textLayerMode,
13068
+ annotationMode: this.#annotationMode,
13069
+ imageResourcesPath: this.imageResourcesPath,
13070
+ enableDetailCanvas: this.enableDetailCanvas,
13071
+ maxCanvasPixels: this.maxCanvasPixels,
13072
+ maxCanvasDim: this.maxCanvasDim,
13073
+ capCanvasAreaFactor: this.capCanvasAreaFactor,
13074
+ enableAutoLinking: this.#enableAutoLinking,
13075
+ commentManager: this.#commentManager,
13076
+ l10n: this.l10n,
13077
+ clonedFrom: this
13078
+ });
13079
+ clone.setPdfPage(this.pdfPage);
13080
+ return clone;
13081
+ }
12663
13082
  #addLayer(div, name) {
12664
13083
  const pos = LAYERS_ORDER.get(name);
12665
13084
  const oldDiv = this.#layers[pos];
@@ -12716,6 +13135,7 @@ class PDFPageView extends BasePDFPageView {
12716
13135
  page: newPageNumber
12717
13136
  }));
12718
13137
  this._textHighlighter.pageIdx = newPageNumber - 1;
13138
+ this.annotationEditorLayer?.updatePageIndex(newPageNumber - 1);
12719
13139
  }
12720
13140
  setPdfPage(pdfPage) {
12721
13141
  if (this._isStandalone && (this.pageColors?.foreground === "CanvasText" || this.pageColors?.background === "Canvas")) {
@@ -12736,6 +13156,14 @@ class PDFPageView extends BasePDFPageView {
12736
13156
  this.reset();
12737
13157
  this.pdfPage?.cleanup();
12738
13158
  }
13159
+ deleteMe(isCut) {
13160
+ if (isCut) {
13161
+ this.div.remove();
13162
+ return;
13163
+ }
13164
+ this.destroy();
13165
+ this.#layerProperties.annotationEditorUIManager?.deletePage(this.id);
13166
+ }
12739
13167
  hasEditableAnnotations() {
12740
13168
  return !!this.annotationLayer?.hasEditableAnnotations();
12741
13169
  }
@@ -13311,17 +13739,19 @@ class PDFPageView extends BasePDFPageView {
13311
13739
  if (this.annotationLayer || this.#annotationMode === AnnotationMode.DISABLE) {
13312
13740
  this.annotationEditorLayer ||= new AnnotationEditorLayerBuilder({
13313
13741
  uiManager: annotationEditorUIManager,
13314
- pdfPage,
13742
+ pageIndex: this.id - 1,
13315
13743
  l10n,
13316
13744
  structTreeLayer: this.structTreeLayer,
13317
13745
  accessibilityManager: this._accessibilityManager,
13318
13746
  annotationLayer: this.annotationLayer?.annotationLayer,
13319
13747
  textLayer: this.textLayer,
13320
13748
  drawLayer: this.drawLayer.getDrawLayer(),
13749
+ clonedFrom: this.#clonedFrom?.annotationEditorLayer,
13321
13750
  onAppend: annotationEditorLayerDiv => {
13322
13751
  this.#addLayer(annotationEditorLayerDiv, "annotationEditorLayer");
13323
13752
  }
13324
13753
  });
13754
+ this.#clonedFrom = null;
13325
13755
  this.#renderAnnotationEditorLayer();
13326
13756
  }
13327
13757
  });
@@ -13371,6 +13801,7 @@ class PDFPageView extends BasePDFPageView {
13371
13801
 
13372
13802
 
13373
13803
 
13804
+
13374
13805
  const DEFAULT_CACHE_SIZE = 10;
13375
13806
  const PagesCountLimit = {
13376
13807
  FORCE_SCROLL_MODE_PAGE: 10000,
@@ -13462,9 +13893,9 @@ class PDFViewer {
13462
13893
  #supportsPinchToZoom = true;
13463
13894
  #textLayerMode = TextLayerMode.ENABLE;
13464
13895
  #viewerAlert = null;
13465
- #pagesMapper = PagesMapper.instance;
13896
+ #copiedPageViews = null;
13466
13897
  constructor(options) {
13467
- const viewerVersion = "5.4.624";
13898
+ const viewerVersion = "5.5.207";
13468
13899
  if (version !== viewerVersion) {
13469
13900
  throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
13470
13901
  }
@@ -13846,7 +14277,6 @@ class PDFViewer {
13846
14277
  this.#annotationEditorUIManager = null;
13847
14278
  this.#annotationEditorMode = AnnotationEditorType.NONE;
13848
14279
  this.#printingAllowed = true;
13849
- this.#pagesMapper.pagesNumber = 0;
13850
14280
  }
13851
14281
  this.pdfDocument = pdfDocument;
13852
14282
  if (!pdfDocument) {
@@ -14055,26 +14485,46 @@ class PDFViewer {
14055
14485
  this._pagesCapability.reject(reason);
14056
14486
  });
14057
14487
  }
14058
- async onBeforePagesEdited({
14059
- pagesMapper
14060
- }) {
14061
- await this._pagesCapability.promise;
14062
- this._currentPageId = pagesMapper.getPageId(this._currentPageNumber);
14063
- }
14064
14488
  onPagesEdited({
14065
- pagesMapper
14489
+ pagesMapper,
14490
+ type,
14491
+ hasBeenCut,
14492
+ pageNumbers
14066
14493
  }) {
14067
- this._currentPageNumber = pagesMapper.getPageNumber(this._currentPageId);
14494
+ if (type === "copy") {
14495
+ this.#copiedPageViews = new Map();
14496
+ for (const pageNum of pageNumbers) {
14497
+ this.#copiedPageViews.set(pageNum, this._pages[pageNum - 1]);
14498
+ }
14499
+ return;
14500
+ }
14501
+ const isCut = type === "cut";
14502
+ if (isCut || type === "delete") {
14503
+ for (const pageNum of pageNumbers) {
14504
+ this._pages[pageNum - 1].deleteMe(isCut);
14505
+ }
14506
+ }
14507
+ this._currentPageNumber = 0;
14068
14508
  const prevPages = this._pages;
14069
14509
  const newPages = this._pages = [];
14070
- for (let i = 0, ii = pagesMapper.pagesNumber; i < ii; i++) {
14071
- const prevPageNumber = pagesMapper.getPrevPageNumber(i + 1) - 1;
14072
- if (prevPageNumber === -1) {
14510
+ for (let i = 1, ii = pagesMapper.pagesNumber; i <= ii; i++) {
14511
+ const prevPageNumber = pagesMapper.getPrevPageNumber(i);
14512
+ if (prevPageNumber < 0) {
14513
+ let page = this.#copiedPageViews.get(-prevPageNumber);
14514
+ if (hasBeenCut) {
14515
+ page.updatePageNumber(i);
14516
+ } else {
14517
+ page = page.clone(i);
14518
+ }
14519
+ newPages.push(page);
14073
14520
  continue;
14074
14521
  }
14075
- const page = prevPages[prevPageNumber];
14076
- newPages[i] = page;
14077
- page.updatePageNumber(i + 1);
14522
+ const page = prevPages[prevPageNumber - 1];
14523
+ newPages.push(page);
14524
+ page.updatePageNumber(i);
14525
+ }
14526
+ if (!isCut) {
14527
+ this.#copiedPageViews = null;
14078
14528
  }
14079
14529
  const viewerElement = this._scrollMode === ScrollMode.PAGE ? null : this.viewer;
14080
14530
  if (viewerElement) {
@@ -14817,7 +15267,7 @@ class PDFViewer {
14817
15267
  this._setCurrentPageNumber(pageNumber, true);
14818
15268
  this.update();
14819
15269
  }
14820
- _getPageAdvance(currentPageNumber, previous = false) {
15270
+ #getPageAdvance(currentPageNumber, previous = false) {
14821
15271
  switch (this._scrollMode) {
14822
15272
  case ScrollMode.WRAPPED:
14823
15273
  {
@@ -14834,11 +15284,7 @@ class PDFViewer {
14834
15284
  if (percent === 0 || widthPercent < 100) {
14835
15285
  continue;
14836
15286
  }
14837
- let yArray = pageLayout.get(y);
14838
- if (!yArray) {
14839
- pageLayout.set(y, yArray ||= []);
14840
- }
14841
- yArray.push(id);
15287
+ pageLayout.getOrInsertComputed(y, makeArr).push(id);
14842
15288
  }
14843
15289
  for (const yArray of pageLayout.values()) {
14844
15290
  const currentIndex = yArray.indexOf(currentPageNumber);
@@ -14925,7 +15371,7 @@ class PDFViewer {
14925
15371
  if (currentPageNumber >= pagesCount) {
14926
15372
  return false;
14927
15373
  }
14928
- const advance = this._getPageAdvance(currentPageNumber, false) || 1;
15374
+ const advance = this.#getPageAdvance(currentPageNumber, false) || 1;
14929
15375
  this.currentPageNumber = Math.min(currentPageNumber + advance, pagesCount);
14930
15376
  return true;
14931
15377
  }
@@ -14934,7 +15380,7 @@ class PDFViewer {
14934
15380
  if (currentPageNumber <= 1) {
14935
15381
  return false;
14936
15382
  }
14937
- const advance = this._getPageAdvance(currentPageNumber, true) || 1;
15383
+ const advance = this.#getPageAdvance(currentPageNumber, true) || 1;
14938
15384
  this.currentPageNumber = Math.max(currentPageNumber - advance, 1);
14939
15385
  return true;
14940
15386
  }
@@ -16471,6 +16917,14 @@ class Toolbar {
16471
16917
  value: this.value
16472
16918
  });
16473
16919
  });
16920
+ eventBus._on("pagesedited", ({
16921
+ pagesMapper
16922
+ }) => {
16923
+ const pagesCount = pagesMapper.pagesNumber;
16924
+ if (pagesCount !== this.pagesCount) {
16925
+ this.setPagesCount(pagesCount, this.hasPageLabels);
16926
+ }
16927
+ });
16474
16928
  scaleSelect.addEventListener("change", function () {
16475
16929
  if (this.value === "custom") {
16476
16930
  return;
@@ -16675,6 +17129,7 @@ const SIDEBAR_RESIZING_CLASS = "viewsManagerResizing";
16675
17129
  const UI_NOTIFICATION_CLASS = "pdfSidebarNotification";
16676
17130
  class ViewsManager extends Sidebar {
16677
17131
  static #l10nDescription = null;
17132
+ #hasAnimations = !window.matchMedia("(prefers-reduced-motion: reduce)").matches;
16678
17133
  constructor({
16679
17134
  elements: {
16680
17135
  outerContainer,
@@ -16689,10 +17144,12 @@ class ViewsManager extends Sidebar {
16689
17144
  outlinesView,
16690
17145
  attachmentsView,
16691
17146
  layersView,
17147
+ viewsManagerAddFileButton,
16692
17148
  viewsManagerCurrentOutlineButton,
16693
17149
  viewsManagerSelectorButton,
16694
17150
  viewsManagerSelectorOptions,
16695
- viewsManagerHeaderLabel
17151
+ viewsManagerHeaderLabel,
17152
+ viewsManagerStatus
16696
17153
  },
16697
17154
  eventBus,
16698
17155
  l10n
@@ -16720,8 +17177,10 @@ class ViewsManager extends Sidebar {
16720
17177
  this.outlinesView = outlinesView;
16721
17178
  this.attachmentsView = attachmentsView;
16722
17179
  this.layersView = layersView;
17180
+ this.viewsManagerAddFileButton = viewsManagerAddFileButton;
16723
17181
  this.viewsManagerCurrentOutlineButton = viewsManagerCurrentOutlineButton;
16724
17182
  this.viewsManagerHeaderLabel = viewsManagerHeaderLabel;
17183
+ this.viewsManagerStatus = viewsManagerStatus;
16725
17184
  this.eventBus = eventBus;
16726
17185
  this.menu = new Menu(viewsManagerSelectorOptions, viewsManagerSelectorButton, [thumbnailButton, outlineButton, attachmentsButton, layersButton]);
16727
17186
  ViewsManager.#l10nDescription ||= Object.freeze({
@@ -16797,6 +17256,8 @@ class ViewsManager extends Sidebar {
16797
17256
  console.error(`PDFSidebar.switchView: "${view}" is not a valid view.`);
16798
17257
  return;
16799
17258
  }
17259
+ this.viewsManagerStatus.hidden = view !== SidebarView.THUMBS;
17260
+ this.viewsManagerAddFileButton.hidden = view !== SidebarView.THUMBS;
16800
17261
  this.viewsManagerCurrentOutlineButton.hidden = view !== SidebarView.OUTLINE;
16801
17262
  this.viewsManagerHeaderLabel.setAttribute("data-l10n-id", ViewsManager.#l10nDescription[titleL10nId] || "");
16802
17263
  this.active = view;
@@ -16825,9 +17286,16 @@ class ViewsManager extends Sidebar {
16825
17286
  this._sidebar.hidden = false;
16826
17287
  toggleExpandedBtn(this.toggleButton, true);
16827
17288
  this.switchView(this.active);
16828
- queueMicrotask(() => {
16829
- this.outerContainer.classList.add("viewsManagerMoving", "viewsManagerOpen");
16830
- });
17289
+ if (this.#hasAnimations) {
17290
+ queueMicrotask(() => {
17291
+ this.outerContainer.classList.add("viewsManagerMoving", "viewsManagerOpen");
17292
+ });
17293
+ } else {
17294
+ this.outerContainer.classList.add("viewsManagerOpen");
17295
+ this.eventBus.dispatch("resize", {
17296
+ source: this
17297
+ });
17298
+ }
16831
17299
  if (this.active === SidebarView.THUMBS) {
16832
17300
  this.onUpdateThumbnails();
16833
17301
  }
@@ -16886,14 +17354,16 @@ class ViewsManager extends Sidebar {
16886
17354
  eventBus,
16887
17355
  outerContainer
16888
17356
  } = this;
16889
- this.sidebarContainer.addEventListener("transitionend", evt => {
16890
- if (evt.target === this.sidebarContainer) {
16891
- outerContainer.classList.remove("viewsManagerMoving");
16892
- eventBus.dispatch("resize", {
16893
- source: this
16894
- });
16895
- }
16896
- });
17357
+ if (this.#hasAnimations) {
17358
+ this.sidebarContainer.addEventListener("transitionend", evt => {
17359
+ if (evt.target === this.sidebarContainer) {
17360
+ outerContainer.classList.remove("viewsManagerMoving");
17361
+ eventBus.dispatch("resize", {
17362
+ source: this
17363
+ });
17364
+ }
17365
+ });
17366
+ }
16897
17367
  this.thumbnailButton.addEventListener("click", () => {
16898
17368
  this.switchView(SidebarView.THUMBS);
16899
17369
  });
@@ -16999,6 +17469,7 @@ class ViewsManager extends Sidebar {
16999
17469
 
17000
17470
 
17001
17471
 
17472
+
17002
17473
 
17003
17474
 
17004
17475
  const FORCE_PAGES_LOADED_TIMEOUT = 10000;
@@ -17311,7 +17782,8 @@ const PDFViewerApplication = {
17311
17782
  abortSignal,
17312
17783
  enableHWA,
17313
17784
  enableSplitMerge: AppOptions.get("enableSplitMerge"),
17314
- manageMenu: appConfig.viewsManager.manageMenu
17785
+ manageMenu: appConfig.viewsManager.manageMenu,
17786
+ addFileButton: appConfig.viewsManager.viewsManagerAddFileButton
17315
17787
  });
17316
17788
  renderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
17317
17789
  }
@@ -17594,7 +18066,7 @@ const PDFViewerApplication = {
17594
18066
  if (isDataScheme(url)) {
17595
18067
  this._hideViewBookmark();
17596
18068
  }
17597
- let title = pdfjs_getPdfFilenameFromUrl(url, "");
18069
+ let title = getPdfFilenameFromUrl(url, "");
17598
18070
  if (!title) {
17599
18071
  try {
17600
18072
  title = decodeURIComponent(getFilenameFromUrl(url));
@@ -17611,7 +18083,7 @@ const PDFViewerApplication = {
17611
18083
  document.title = `${editorIndicator ? "* " : ""}${title}`;
17612
18084
  },
17613
18085
  get _docFilename() {
17614
- return this._contentDispositionFilename || pdfjs_getPdfFilenameFromUrl(this.url);
18086
+ return this._contentDispositionFilename || getPdfFilenameFromUrl(this.url);
17615
18087
  },
17616
18088
  get _docTitle() {
17617
18089
  const {
@@ -18313,7 +18785,6 @@ const PDFViewerApplication = {
18313
18785
  eventBus._on("fileinputchange", onFileInputChange.bind(this), opts);
18314
18786
  eventBus._on("openfile", onOpenFile.bind(this), opts);
18315
18787
  eventBus._on("pagesedited", this.onPagesEdited.bind(this), opts);
18316
- eventBus._on("beforepagesedited", this.onBeforePagesEdited.bind(this), opts);
18317
18788
  eventBus._on("savepageseditedpdf", this.onSavePagesEditedPDF.bind(this), opts);
18318
18789
  },
18319
18790
  bindWindowEvents() {
@@ -18457,29 +18928,16 @@ const PDFViewerApplication = {
18457
18928
  this.findBar?.close();
18458
18929
  await Promise.all([this.l10n?.destroy(), this.close()]);
18459
18930
  },
18460
- onBeforePagesEdited(data) {
18461
- this.pdfViewer.onBeforePagesEdited(data);
18462
- },
18463
18931
  onPagesEdited(data) {
18464
18932
  this.pdfViewer.onPagesEdited(data);
18465
18933
  },
18466
18934
  async onSavePagesEditedPDF({
18467
- data: {
18468
- includePages,
18469
- excludePages,
18470
- pageIndices
18471
- }
18935
+ data: extractParams
18472
18936
  }) {
18473
18937
  if (!this.pdfDocument) {
18474
18938
  return;
18475
18939
  }
18476
- const pageInfo = {
18477
- document: null,
18478
- includePages,
18479
- excludePages,
18480
- pageIndices
18481
- };
18482
- const modifiedPdfBytes = await this.pdfDocument.extractPages([pageInfo]);
18940
+ const modifiedPdfBytes = await this.pdfDocument.extractPages(extractParams);
18483
18941
  if (!modifiedPdfBytes) {
18484
18942
  console.error("Something wrong happened when saving the edited PDF.\nPlease file a bug.");
18485
18943
  return;
@@ -18515,9 +18973,7 @@ const PDFViewerApplication = {
18515
18973
  }
18516
18974
  };
18517
18975
  initCom(PDFViewerApplication);
18518
- {
18519
- PDFPrintServiceFactory.initGlobals(PDFViewerApplication);
18520
- }
18976
+ PDFPrintServiceFactory.initGlobals(PDFViewerApplication);
18521
18977
  {
18522
18978
  const HOSTED_VIEWER_ORIGINS = new Set(["null", "http://mozilla.github.io", "https://mozilla.github.io"]);
18523
18979
  var validateFileURL = function (file) {
@@ -19114,6 +19570,7 @@ function beforeUnload(evt) {
19114
19570
 
19115
19571
 
19116
19572
 
19573
+
19117
19574
  const AppConstants = {
19118
19575
  LinkTarget: LinkTarget,
19119
19576
  RenderingStates: RenderingStates,
@@ -19199,6 +19656,7 @@ function getViewerConfiguration() {
19199
19656
  viewsManagerAddFileButton: document.getElementById("viewsManagerAddFileButton"),
19200
19657
  viewsManagerCurrentOutlineButton: document.getElementById("viewsManagerCurrentOutlineButton"),
19201
19658
  viewsManagerHeaderLabel: document.getElementById("viewsManagerHeaderLabel"),
19659
+ viewsManagerStatus: document.getElementById("viewsManagerStatus"),
19202
19660
  manageMenu: {
19203
19661
  button: document.getElementById("viewsManagerStatusActionButton"),
19204
19662
  menu: document.getElementById("viewsManagerStatusActionOptions"),
@@ -19277,10 +19735,7 @@ function getViewerConfiguration() {
19277
19735
  altTextSettingsDialog: {
19278
19736
  dialog: document.getElementById("altTextSettingsDialog"),
19279
19737
  createModelButton: document.getElementById("createModelButton"),
19280
- aiModelSettings: document.getElementById("aiModelSettings"),
19281
19738
  learnMore: document.getElementById("altTextSettingsLearnMore"),
19282
- deleteModelButton: document.getElementById("deleteModelButton"),
19283
- downloadModelButton: document.getElementById("downloadModelButton"),
19284
19739
  showAltTextDialogButton: document.getElementById("showAltTextDialogButton"),
19285
19740
  altTextSettingsCloseButton: document.getElementById("altTextSettingsCloseButton"),
19286
19741
  closeButton: document.getElementById("altTextSettingsCloseButton")