Backed out 7 changesets (bug 1942424) for causing frequent crashes. a=backout
[gecko.git] / toolkit / components / pdfjs / content / web / viewer.mjs
blobf412223a5ea7f4cd7ac7c8c29535161ad054b59f
1 /**
2  * @licstart The following is the entire license notice for the
3  * JavaScript code in this page
4  *
5  * Copyright 2024 Mozilla Foundation
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * @licend The above is the entire license notice for the
20  * JavaScript code in this page
21  */
23 /******/ // The require scope
24 /******/ var __webpack_require__ = {};
25 /******/ 
26 /************************************************************************/
27 /******/ /* webpack/runtime/define property getters */
28 /******/ (() => {
29 /******/        // define getter functions for harmony exports
30 /******/        __webpack_require__.d = (exports, definition) => {
31 /******/                for(var key in definition) {
32 /******/                        if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
33 /******/                                Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
34 /******/                        }
35 /******/                }
36 /******/        };
37 /******/ })();
38 /******/ 
39 /******/ /* webpack/runtime/hasOwnProperty shorthand */
40 /******/ (() => {
41 /******/        __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
42 /******/ })();
43 /******/ 
44 /************************************************************************/
45 var __webpack_exports__ = {};
47 // EXPORTS
48 __webpack_require__.d(__webpack_exports__, {
49   PDFViewerApplication: () => (/* reexport */ PDFViewerApplication),
50   PDFViewerApplicationConstants: () => (/* binding */ AppConstants),
51   PDFViewerApplicationOptions: () => (/* reexport */ AppOptions)
52 });
54 ;// ./web/ui_utils.js
55 const DEFAULT_SCALE_VALUE = "auto";
56 const DEFAULT_SCALE = 1.0;
57 const DEFAULT_SCALE_DELTA = 1.1;
58 const MIN_SCALE = 0.1;
59 const MAX_SCALE = 10.0;
60 const UNKNOWN_SCALE = 0;
61 const MAX_AUTO_SCALE = 1.25;
62 const SCROLLBAR_PADDING = 40;
63 const VERTICAL_PADDING = 5;
64 const RenderingStates = {
65   INITIAL: 0,
66   RUNNING: 1,
67   PAUSED: 2,
68   FINISHED: 3
70 const PresentationModeState = {
71   UNKNOWN: 0,
72   NORMAL: 1,
73   CHANGING: 2,
74   FULLSCREEN: 3
76 const SidebarView = {
77   UNKNOWN: -1,
78   NONE: 0,
79   THUMBS: 1,
80   OUTLINE: 2,
81   ATTACHMENTS: 3,
82   LAYERS: 4
84 const TextLayerMode = {
85   DISABLE: 0,
86   ENABLE: 1,
87   ENABLE_PERMISSIONS: 2
89 const ScrollMode = {
90   UNKNOWN: -1,
91   VERTICAL: 0,
92   HORIZONTAL: 1,
93   WRAPPED: 2,
94   PAGE: 3
96 const SpreadMode = {
97   UNKNOWN: -1,
98   NONE: 0,
99   ODD: 1,
100   EVEN: 2
102 const CursorTool = {
103   SELECT: 0,
104   HAND: 1,
105   ZOOM: 2
107 const AutoPrintRegExp = /\bprint\s*\(/;
108 function scrollIntoView(element, spot, scrollMatches = false) {
109   let parent = element.offsetParent;
110   if (!parent) {
111     console.error("offsetParent is not set -- cannot scroll");
112     return;
113   }
114   let offsetY = element.offsetTop + element.clientTop;
115   let offsetX = element.offsetLeft + element.clientLeft;
116   while (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth || scrollMatches && (parent.classList.contains("markedContent") || getComputedStyle(parent).overflow === "hidden")) {
117     offsetY += parent.offsetTop;
118     offsetX += parent.offsetLeft;
119     parent = parent.offsetParent;
120     if (!parent) {
121       return;
122     }
123   }
124   if (spot) {
125     if (spot.top !== undefined) {
126       offsetY += spot.top;
127     }
128     if (spot.left !== undefined) {
129       offsetX += spot.left;
130       parent.scrollLeft = offsetX;
131     }
132   }
133   parent.scrollTop = offsetY;
135 function watchScroll(viewAreaElement, callback, abortSignal = undefined) {
136   const debounceScroll = function (evt) {
137     if (rAF) {
138       return;
139     }
140     rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {
141       rAF = null;
142       const currentX = viewAreaElement.scrollLeft;
143       const lastX = state.lastX;
144       if (currentX !== lastX) {
145         state.right = currentX > lastX;
146       }
147       state.lastX = currentX;
148       const currentY = viewAreaElement.scrollTop;
149       const lastY = state.lastY;
150       if (currentY !== lastY) {
151         state.down = currentY > lastY;
152       }
153       state.lastY = currentY;
154       callback(state);
155     });
156   };
157   const state = {
158     right: true,
159     down: true,
160     lastX: viewAreaElement.scrollLeft,
161     lastY: viewAreaElement.scrollTop,
162     _eventHandler: debounceScroll
163   };
164   let rAF = null;
165   viewAreaElement.addEventListener("scroll", debounceScroll, {
166     useCapture: true,
167     signal: abortSignal
168   });
169   abortSignal?.addEventListener("abort", () => window.cancelAnimationFrame(rAF), {
170     once: true
171   });
172   return state;
174 function parseQueryString(query) {
175   const params = new Map();
176   for (const [key, value] of new URLSearchParams(query)) {
177     params.set(key.toLowerCase(), value);
178   }
179   return params;
181 const InvisibleCharsRegExp = /[\x00-\x1F]/g;
182 function removeNullCharacters(str, replaceInvisible = false) {
183   if (!InvisibleCharsRegExp.test(str)) {
184     return str;
185   }
186   if (replaceInvisible) {
187     return str.replaceAll(InvisibleCharsRegExp, m => m === "\x00" ? "" : " ");
188   }
189   return str.replaceAll("\x00", "");
191 function binarySearchFirstItem(items, condition, start = 0) {
192   let minIndex = start;
193   let maxIndex = items.length - 1;
194   if (maxIndex < 0 || !condition(items[maxIndex])) {
195     return items.length;
196   }
197   if (condition(items[minIndex])) {
198     return minIndex;
199   }
200   while (minIndex < maxIndex) {
201     const currentIndex = minIndex + maxIndex >> 1;
202     const currentItem = items[currentIndex];
203     if (condition(currentItem)) {
204       maxIndex = currentIndex;
205     } else {
206       minIndex = currentIndex + 1;
207     }
208   }
209   return minIndex;
211 function approximateFraction(x) {
212   if (Math.floor(x) === x) {
213     return [x, 1];
214   }
215   const xinv = 1 / x;
216   const limit = 8;
217   if (xinv > limit) {
218     return [1, limit];
219   } else if (Math.floor(xinv) === xinv) {
220     return [1, xinv];
221   }
222   const x_ = x > 1 ? xinv : x;
223   let a = 0,
224     b = 1,
225     c = 1,
226     d = 1;
227   while (true) {
228     const p = a + c,
229       q = b + d;
230     if (q > limit) {
231       break;
232     }
233     if (x_ <= p / q) {
234       c = p;
235       d = q;
236     } else {
237       a = p;
238       b = q;
239     }
240   }
241   let result;
242   if (x_ - a / b < c / d - x_) {
243     result = x_ === x ? [a, b] : [b, a];
244   } else {
245     result = x_ === x ? [c, d] : [d, c];
246   }
247   return result;
249 function floorToDivide(x, div) {
250   return x - x % div;
252 function getPageSizeInches({
253   view,
254   userUnit,
255   rotate
256 }) {
257   const [x1, y1, x2, y2] = view;
258   const changeOrientation = rotate % 180 !== 0;
259   const width = (x2 - x1) / 72 * userUnit;
260   const height = (y2 - y1) / 72 * userUnit;
261   return {
262     width: changeOrientation ? height : width,
263     height: changeOrientation ? width : height
264   };
266 function backtrackBeforeAllVisibleElements(index, views, top) {
267   if (index < 2) {
268     return index;
269   }
270   let elt = views[index].div;
271   let pageTop = elt.offsetTop + elt.clientTop;
272   if (pageTop >= top) {
273     elt = views[index - 1].div;
274     pageTop = elt.offsetTop + elt.clientTop;
275   }
276   for (let i = index - 2; i >= 0; --i) {
277     elt = views[i].div;
278     if (elt.offsetTop + elt.clientTop + elt.clientHeight <= pageTop) {
279       break;
280     }
281     index = i;
282   }
283   return index;
285 function getVisibleElements({
286   scrollEl,
287   views,
288   sortByVisibility = false,
289   horizontal = false,
290   rtl = false
291 }) {
292   const top = scrollEl.scrollTop,
293     bottom = top + scrollEl.clientHeight;
294   const left = scrollEl.scrollLeft,
295     right = left + scrollEl.clientWidth;
296   function isElementBottomAfterViewTop(view) {
297     const element = view.div;
298     const elementBottom = element.offsetTop + element.clientTop + element.clientHeight;
299     return elementBottom > top;
300   }
301   function isElementNextAfterViewHorizontally(view) {
302     const element = view.div;
303     const elementLeft = element.offsetLeft + element.clientLeft;
304     const elementRight = elementLeft + element.clientWidth;
305     return rtl ? elementLeft < right : elementRight > left;
306   }
307   const visible = [],
308     ids = new Set(),
309     numViews = views.length;
310   let firstVisibleElementInd = binarySearchFirstItem(views, horizontal ? isElementNextAfterViewHorizontally : isElementBottomAfterViewTop);
311   if (firstVisibleElementInd > 0 && firstVisibleElementInd < numViews && !horizontal) {
312     firstVisibleElementInd = backtrackBeforeAllVisibleElements(firstVisibleElementInd, views, top);
313   }
314   let lastEdge = horizontal ? right : -1;
315   for (let i = firstVisibleElementInd; i < numViews; i++) {
316     const view = views[i],
317       element = view.div;
318     const currentWidth = element.offsetLeft + element.clientLeft;
319     const currentHeight = element.offsetTop + element.clientTop;
320     const viewWidth = element.clientWidth,
321       viewHeight = element.clientHeight;
322     const viewRight = currentWidth + viewWidth;
323     const viewBottom = currentHeight + viewHeight;
324     if (lastEdge === -1) {
325       if (viewBottom >= bottom) {
326         lastEdge = viewBottom;
327       }
328     } else if ((horizontal ? currentWidth : currentHeight) > lastEdge) {
329       break;
330     }
331     if (viewBottom <= top || currentHeight >= bottom || viewRight <= left || currentWidth >= right) {
332       continue;
333     }
334     const hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, viewBottom - bottom);
335     const hiddenWidth = Math.max(0, left - currentWidth) + Math.max(0, viewRight - right);
336     const fractionHeight = (viewHeight - hiddenHeight) / viewHeight,
337       fractionWidth = (viewWidth - hiddenWidth) / viewWidth;
338     const percent = fractionHeight * fractionWidth * 100 | 0;
339     visible.push({
340       id: view.id,
341       x: currentWidth,
342       y: currentHeight,
343       view,
344       percent,
345       widthPercent: fractionWidth * 100 | 0
346     });
347     ids.add(view.id);
348   }
349   const first = visible[0],
350     last = visible.at(-1);
351   if (sortByVisibility) {
352     visible.sort(function (a, b) {
353       const pc = a.percent - b.percent;
354       if (Math.abs(pc) > 0.001) {
355         return -pc;
356       }
357       return a.id - b.id;
358     });
359   }
360   return {
361     first,
362     last,
363     views: visible,
364     ids
365   };
367 function normalizeWheelEventDirection(evt) {
368   let delta = Math.hypot(evt.deltaX, evt.deltaY);
369   const angle = Math.atan2(evt.deltaY, evt.deltaX);
370   if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) {
371     delta = -delta;
372   }
373   return delta;
375 function normalizeWheelEventDelta(evt) {
376   const deltaMode = evt.deltaMode;
377   let delta = normalizeWheelEventDirection(evt);
378   const MOUSE_PIXELS_PER_LINE = 30;
379   const MOUSE_LINES_PER_PAGE = 30;
380   if (deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
381     delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE;
382   } else if (deltaMode === WheelEvent.DOM_DELTA_LINE) {
383     delta /= MOUSE_LINES_PER_PAGE;
384   }
385   return delta;
387 function isValidRotation(angle) {
388   return Number.isInteger(angle) && angle % 90 === 0;
390 function isValidScrollMode(mode) {
391   return Number.isInteger(mode) && Object.values(ScrollMode).includes(mode) && mode !== ScrollMode.UNKNOWN;
393 function isValidSpreadMode(mode) {
394   return Number.isInteger(mode) && Object.values(SpreadMode).includes(mode) && mode !== SpreadMode.UNKNOWN;
396 function isPortraitOrientation(size) {
397   return size.width <= size.height;
399 const animationStarted = new Promise(function (resolve) {
400   window.requestAnimationFrame(resolve);
402 const docStyle = document.documentElement.style;
403 function clamp(v, min, max) {
404   return Math.min(Math.max(v, min), max);
406 class ProgressBar {
407   #classList = null;
408   #disableAutoFetchTimeout = null;
409   #percent = 0;
410   #style = null;
411   #visible = true;
412   constructor(bar) {
413     this.#classList = bar.classList;
414     this.#style = bar.style;
415   }
416   get percent() {
417     return this.#percent;
418   }
419   set percent(val) {
420     this.#percent = clamp(val, 0, 100);
421     if (isNaN(val)) {
422       this.#classList.add("indeterminate");
423       return;
424     }
425     this.#classList.remove("indeterminate");
426     this.#style.setProperty("--progressBar-percent", `${this.#percent}%`);
427   }
428   setWidth(viewer) {
429     if (!viewer) {
430       return;
431     }
432     const container = viewer.parentNode;
433     const scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
434     if (scrollbarWidth > 0) {
435       this.#style.setProperty("--progressBar-end-offset", `${scrollbarWidth}px`);
436     }
437   }
438   setDisableAutoFetch(delay = 5000) {
439     if (this.#percent === 100 || isNaN(this.#percent)) {
440       return;
441     }
442     if (this.#disableAutoFetchTimeout) {
443       clearTimeout(this.#disableAutoFetchTimeout);
444     }
445     this.show();
446     this.#disableAutoFetchTimeout = setTimeout(() => {
447       this.#disableAutoFetchTimeout = null;
448       this.hide();
449     }, delay);
450   }
451   hide() {
452     if (!this.#visible) {
453       return;
454     }
455     this.#visible = false;
456     this.#classList.add("hidden");
457   }
458   show() {
459     if (this.#visible) {
460       return;
461     }
462     this.#visible = true;
463     this.#classList.remove("hidden");
464   }
466 function getActiveOrFocusedElement() {
467   let curRoot = document;
468   let curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus");
469   while (curActiveOrFocused?.shadowRoot) {
470     curRoot = curActiveOrFocused.shadowRoot;
471     curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus");
472   }
473   return curActiveOrFocused;
475 function apiPageLayoutToViewerModes(layout) {
476   let scrollMode = ScrollMode.VERTICAL,
477     spreadMode = SpreadMode.NONE;
478   switch (layout) {
479     case "SinglePage":
480       scrollMode = ScrollMode.PAGE;
481       break;
482     case "OneColumn":
483       break;
484     case "TwoPageLeft":
485       scrollMode = ScrollMode.PAGE;
486     case "TwoColumnLeft":
487       spreadMode = SpreadMode.ODD;
488       break;
489     case "TwoPageRight":
490       scrollMode = ScrollMode.PAGE;
491     case "TwoColumnRight":
492       spreadMode = SpreadMode.EVEN;
493       break;
494   }
495   return {
496     scrollMode,
497     spreadMode
498   };
500 function apiPageModeToSidebarView(mode) {
501   switch (mode) {
502     case "UseNone":
503       return SidebarView.NONE;
504     case "UseThumbs":
505       return SidebarView.THUMBS;
506     case "UseOutlines":
507       return SidebarView.OUTLINE;
508     case "UseAttachments":
509       return SidebarView.ATTACHMENTS;
510     case "UseOC":
511       return SidebarView.LAYERS;
512   }
513   return SidebarView.NONE;
515 function toggleCheckedBtn(button, toggle, view = null) {
516   button.classList.toggle("toggled", toggle);
517   button.setAttribute("aria-checked", toggle);
518   view?.classList.toggle("hidden", !toggle);
520 function toggleExpandedBtn(button, toggle, view = null) {
521   button.classList.toggle("toggled", toggle);
522   button.setAttribute("aria-expanded", toggle);
523   view?.classList.toggle("hidden", !toggle);
525 const calcRound = Math.fround;
527 ;// ./web/app_options.js
528 const OptionKind = {
529   BROWSER: 0x01,
530   VIEWER: 0x02,
531   API: 0x04,
532   WORKER: 0x08,
533   EVENT_DISPATCH: 0x10,
534   PREFERENCE: 0x80
536 const Type = {
537   BOOLEAN: 0x01,
538   NUMBER: 0x02,
539   OBJECT: 0x04,
540   STRING: 0x08,
541   UNDEFINED: 0x10
543 const defaultOptions = {
544   allowedGlobalEvents: {
545     value: null,
546     kind: OptionKind.BROWSER
547   },
548   canvasMaxAreaInBytes: {
549     value: -1,
550     kind: OptionKind.BROWSER + OptionKind.API
551   },
552   isInAutomation: {
553     value: false,
554     kind: OptionKind.BROWSER
555   },
556   localeProperties: {
557     value: null,
558     kind: OptionKind.BROWSER
559   },
560   nimbusDataStr: {
561     value: "",
562     kind: OptionKind.BROWSER
563   },
564   supportsCaretBrowsingMode: {
565     value: false,
566     kind: OptionKind.BROWSER
567   },
568   supportsDocumentFonts: {
569     value: true,
570     kind: OptionKind.BROWSER
571   },
572   supportsIntegratedFind: {
573     value: false,
574     kind: OptionKind.BROWSER
575   },
576   supportsMouseWheelZoomCtrlKey: {
577     value: true,
578     kind: OptionKind.BROWSER
579   },
580   supportsMouseWheelZoomMetaKey: {
581     value: true,
582     kind: OptionKind.BROWSER
583   },
584   supportsPinchToZoom: {
585     value: true,
586     kind: OptionKind.BROWSER
587   },
588   toolbarDensity: {
589     value: 0,
590     kind: OptionKind.BROWSER + OptionKind.EVENT_DISPATCH
591   },
592   altTextLearnMoreUrl: {
593     value: "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/pdf-alt-text",
594     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
595   },
596   annotationEditorMode: {
597     value: 0,
598     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
599   },
600   annotationMode: {
601     value: 2,
602     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
603   },
604   cursorToolOnLoad: {
605     value: 0,
606     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
607   },
608   debuggerSrc: {
609     value: "./debugger.mjs",
610     kind: OptionKind.VIEWER
611   },
612   defaultZoomDelay: {
613     value: 400,
614     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
615   },
616   defaultZoomValue: {
617     value: "",
618     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
619   },
620   disableHistory: {
621     value: false,
622     kind: OptionKind.VIEWER
623   },
624   disablePageLabels: {
625     value: false,
626     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
627   },
628   enableAltText: {
629     value: false,
630     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
631   },
632   enableAltTextModelDownload: {
633     value: true,
634     kind: OptionKind.VIEWER + OptionKind.PREFERENCE + OptionKind.EVENT_DISPATCH
635   },
636   enableGuessAltText: {
637     value: true,
638     kind: OptionKind.VIEWER + OptionKind.PREFERENCE + OptionKind.EVENT_DISPATCH
639   },
640   enableHighlightFloatingButton: {
641     value: false,
642     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
643   },
644   enableNewAltTextWhenAddingImage: {
645     value: true,
646     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
647   },
648   enablePermissions: {
649     value: false,
650     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
651   },
652   enablePrintAutoRotate: {
653     value: true,
654     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
655   },
656   enableScripting: {
657     value: true,
658     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
659   },
660   enableSignatureEditor: {
661     value: false,
662     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
663   },
664   enableUpdatedAddImage: {
665     value: false,
666     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
667   },
668   externalLinkRel: {
669     value: "noopener noreferrer nofollow",
670     kind: OptionKind.VIEWER
671   },
672   externalLinkTarget: {
673     value: 0,
674     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
675   },
676   highlightEditorColors: {
677     value: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",
678     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
679   },
680   historyUpdateUrl: {
681     value: false,
682     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
683   },
684   ignoreDestinationZoom: {
685     value: false,
686     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
687   },
688   imageResourcesPath: {
689     value: "resource://pdf.js/web/images/",
690     kind: OptionKind.VIEWER
691   },
692   maxCanvasPixels: {
693     value: 2 ** 25,
694     kind: OptionKind.VIEWER
695   },
696   forcePageColors: {
697     value: false,
698     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
699   },
700   pageColorsBackground: {
701     value: "Canvas",
702     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
703   },
704   pageColorsForeground: {
705     value: "CanvasText",
706     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
707   },
708   pdfBugEnabled: {
709     value: false,
710     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
711   },
712   printResolution: {
713     value: 150,
714     kind: OptionKind.VIEWER
715   },
716   sidebarViewOnLoad: {
717     value: -1,
718     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
719   },
720   scrollModeOnLoad: {
721     value: -1,
722     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
723   },
724   spreadModeOnLoad: {
725     value: -1,
726     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
727   },
728   textLayerMode: {
729     value: 1,
730     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
731   },
732   viewOnLoad: {
733     value: 0,
734     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
735   },
736   cMapPacked: {
737     value: true,
738     kind: OptionKind.API
739   },
740   cMapUrl: {
741     value: "resource://pdf.js/web/cmaps/",
742     kind: OptionKind.API
743   },
744   disableAutoFetch: {
745     value: false,
746     kind: OptionKind.API + OptionKind.PREFERENCE
747   },
748   disableFontFace: {
749     value: false,
750     kind: OptionKind.API + OptionKind.PREFERENCE
751   },
752   disableRange: {
753     value: false,
754     kind: OptionKind.API + OptionKind.PREFERENCE
755   },
756   disableStream: {
757     value: false,
758     kind: OptionKind.API + OptionKind.PREFERENCE
759   },
760   docBaseUrl: {
761     value: "",
762     kind: OptionKind.API
763   },
764   enableHWA: {
765     value: false,
766     kind: OptionKind.API + OptionKind.VIEWER + OptionKind.PREFERENCE
767   },
768   enableXfa: {
769     value: true,
770     kind: OptionKind.API + OptionKind.PREFERENCE
771   },
772   fontExtraProperties: {
773     value: false,
774     kind: OptionKind.API
775   },
776   isEvalSupported: {
777     value: true,
778     kind: OptionKind.API
779   },
780   isOffscreenCanvasSupported: {
781     value: true,
782     kind: OptionKind.API
783   },
784   maxImageSize: {
785     value: -1,
786     kind: OptionKind.API
787   },
788   pdfBug: {
789     value: false,
790     kind: OptionKind.API
791   },
792   standardFontDataUrl: {
793     value: "resource://pdf.js/web/standard_fonts/",
794     kind: OptionKind.API
795   },
796   useSystemFonts: {
797     value: undefined,
798     kind: OptionKind.API,
799     type: Type.BOOLEAN + Type.UNDEFINED
800   },
801   verbosity: {
802     value: 1,
803     kind: OptionKind.API
804   },
805   wasmUrl: {
806     value: "resource://pdf.js/web/wasm/",
807     kind: OptionKind.API
808   },
809   workerPort: {
810     value: null,
811     kind: OptionKind.WORKER
812   },
813   workerSrc: {
814     value: "resource://pdf.js/build/pdf.worker.mjs",
815     kind: OptionKind.WORKER
816   }
818 class AppOptions {
819   static eventBus;
820   static #opts = new Map();
821   static {
822     for (const name in defaultOptions) {
823       this.#opts.set(name, defaultOptions[name].value);
824     }
825   }
826   static get(name) {
827     return this.#opts.get(name);
828   }
829   static getAll(kind = null, defaultOnly = false) {
830     const options = Object.create(null);
831     for (const name in defaultOptions) {
832       const defaultOpt = defaultOptions[name];
833       if (kind && !(kind & defaultOpt.kind)) {
834         continue;
835       }
836       options[name] = !defaultOnly ? this.#opts.get(name) : defaultOpt.value;
837     }
838     return options;
839   }
840   static set(name, value) {
841     this.setAll({
842       [name]: value
843     });
844   }
845   static setAll(options, prefs = false) {
846     let events;
847     for (const name in options) {
848       const defaultOpt = defaultOptions[name],
849         userOpt = options[name];
850       if (!defaultOpt || !(typeof userOpt === typeof defaultOpt.value || Type[(typeof userOpt).toUpperCase()] & defaultOpt.type)) {
851         continue;
852       }
853       const {
854         kind
855       } = defaultOpt;
856       if (prefs && !(kind & OptionKind.BROWSER || kind & OptionKind.PREFERENCE)) {
857         continue;
858       }
859       if (this.eventBus && kind & OptionKind.EVENT_DISPATCH) {
860         (events ||= new Map()).set(name, userOpt);
861       }
862       this.#opts.set(name, userOpt);
863     }
864     if (events) {
865       for (const [name, value] of events) {
866         this.eventBus.dispatch(name.toLowerCase(), {
867           source: this,
868           value
869         });
870       }
871     }
872   }
875 ;// ./web/pdf_link_service.js
877 const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
878 const LinkTarget = {
879   NONE: 0,
880   SELF: 1,
881   BLANK: 2,
882   PARENT: 3,
883   TOP: 4
885 class PDFLinkService {
886   externalLinkEnabled = true;
887   constructor({
888     eventBus,
889     externalLinkTarget = null,
890     externalLinkRel = null,
891     ignoreDestinationZoom = false
892   } = {}) {
893     this.eventBus = eventBus;
894     this.externalLinkTarget = externalLinkTarget;
895     this.externalLinkRel = externalLinkRel;
896     this._ignoreDestinationZoom = ignoreDestinationZoom;
897     this.baseUrl = null;
898     this.pdfDocument = null;
899     this.pdfViewer = null;
900     this.pdfHistory = null;
901   }
902   setDocument(pdfDocument, baseUrl = null) {
903     this.baseUrl = baseUrl;
904     this.pdfDocument = pdfDocument;
905   }
906   setViewer(pdfViewer) {
907     this.pdfViewer = pdfViewer;
908   }
909   setHistory(pdfHistory) {
910     this.pdfHistory = pdfHistory;
911   }
912   get pagesCount() {
913     return this.pdfDocument ? this.pdfDocument.numPages : 0;
914   }
915   get page() {
916     return this.pdfDocument ? this.pdfViewer.currentPageNumber : 1;
917   }
918   set page(value) {
919     if (this.pdfDocument) {
920       this.pdfViewer.currentPageNumber = value;
921     }
922   }
923   get rotation() {
924     return this.pdfDocument ? this.pdfViewer.pagesRotation : 0;
925   }
926   set rotation(value) {
927     if (this.pdfDocument) {
928       this.pdfViewer.pagesRotation = value;
929     }
930   }
931   get isInPresentationMode() {
932     return this.pdfDocument ? this.pdfViewer.isInPresentationMode : false;
933   }
934   async goToDestination(dest) {
935     if (!this.pdfDocument) {
936       return;
937     }
938     let namedDest, explicitDest, pageNumber;
939     if (typeof dest === "string") {
940       namedDest = dest;
941       explicitDest = await this.pdfDocument.getDestination(dest);
942     } else {
943       namedDest = null;
944       explicitDest = await dest;
945     }
946     if (!Array.isArray(explicitDest)) {
947       console.error(`goToDestination: "${explicitDest}" is not a valid destination array, for dest="${dest}".`);
948       return;
949     }
950     const [destRef] = explicitDest;
951     if (destRef && typeof destRef === "object") {
952       pageNumber = this.pdfDocument.cachedPageNumber(destRef);
953       if (!pageNumber) {
954         try {
955           pageNumber = (await this.pdfDocument.getPageIndex(destRef)) + 1;
956         } catch {
957           console.error(`goToDestination: "${destRef}" is not a valid page reference, for dest="${dest}".`);
958           return;
959         }
960       }
961     } else if (Number.isInteger(destRef)) {
962       pageNumber = destRef + 1;
963     }
964     if (!pageNumber || pageNumber < 1 || pageNumber > this.pagesCount) {
965       console.error(`goToDestination: "${pageNumber}" is not a valid page number, for dest="${dest}".`);
966       return;
967     }
968     if (this.pdfHistory) {
969       this.pdfHistory.pushCurrentPosition();
970       this.pdfHistory.push({
971         namedDest,
972         explicitDest,
973         pageNumber
974       });
975     }
976     this.pdfViewer.scrollPageIntoView({
977       pageNumber,
978       destArray: explicitDest,
979       ignoreDestinationZoom: this._ignoreDestinationZoom
980     });
981   }
982   goToPage(val) {
983     if (!this.pdfDocument) {
984       return;
985     }
986     const pageNumber = typeof val === "string" && this.pdfViewer.pageLabelToPageNumber(val) || val | 0;
987     if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.pagesCount)) {
988       console.error(`PDFLinkService.goToPage: "${val}" is not a valid page.`);
989       return;
990     }
991     if (this.pdfHistory) {
992       this.pdfHistory.pushCurrentPosition();
993       this.pdfHistory.pushPage(pageNumber);
994     }
995     this.pdfViewer.scrollPageIntoView({
996       pageNumber
997     });
998   }
999   addLinkAttributes(link, url, newWindow = false) {
1000     if (!url || typeof url !== "string") {
1001       throw new Error('A valid "url" parameter must provided.');
1002     }
1003     const target = newWindow ? LinkTarget.BLANK : this.externalLinkTarget,
1004       rel = this.externalLinkRel;
1005     if (this.externalLinkEnabled) {
1006       link.href = link.title = url;
1007     } else {
1008       link.href = "";
1009       link.title = `Disabled: ${url}`;
1010       link.onclick = () => false;
1011     }
1012     let targetStr = "";
1013     switch (target) {
1014       case LinkTarget.NONE:
1015         break;
1016       case LinkTarget.SELF:
1017         targetStr = "_self";
1018         break;
1019       case LinkTarget.BLANK:
1020         targetStr = "_blank";
1021         break;
1022       case LinkTarget.PARENT:
1023         targetStr = "_parent";
1024         break;
1025       case LinkTarget.TOP:
1026         targetStr = "_top";
1027         break;
1028     }
1029     link.target = targetStr;
1030     link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL;
1031   }
1032   getDestinationHash(dest) {
1033     if (typeof dest === "string") {
1034       if (dest.length > 0) {
1035         return this.getAnchorUrl("#" + escape(dest));
1036       }
1037     } else if (Array.isArray(dest)) {
1038       const str = JSON.stringify(dest);
1039       if (str.length > 0) {
1040         return this.getAnchorUrl("#" + escape(str));
1041       }
1042     }
1043     return this.getAnchorUrl("");
1044   }
1045   getAnchorUrl(anchor) {
1046     return this.baseUrl ? this.baseUrl + anchor : anchor;
1047   }
1048   setHash(hash) {
1049     if (!this.pdfDocument) {
1050       return;
1051     }
1052     let pageNumber, dest;
1053     if (hash.includes("=")) {
1054       const params = parseQueryString(hash);
1055       if (params.has("search")) {
1056         const query = params.get("search").replaceAll('"', ""),
1057           phrase = params.get("phrase") === "true";
1058         this.eventBus.dispatch("findfromurlhash", {
1059           source: this,
1060           query: phrase ? query : query.match(/\S+/g)
1061         });
1062       }
1063       if (params.has("page")) {
1064         pageNumber = params.get("page") | 0 || 1;
1065       }
1066       if (params.has("zoom")) {
1067         const zoomArgs = params.get("zoom").split(",");
1068         const zoomArg = zoomArgs[0];
1069         const zoomArgNumber = parseFloat(zoomArg);
1070         if (!zoomArg.includes("Fit")) {
1071           dest = [null, {
1072             name: "XYZ"
1073           }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null, zoomArgs.length > 2 ? zoomArgs[2] | 0 : null, zoomArgNumber ? zoomArgNumber / 100 : zoomArg];
1074         } else if (zoomArg === "Fit" || zoomArg === "FitB") {
1075           dest = [null, {
1076             name: zoomArg
1077           }];
1078         } else if (zoomArg === "FitH" || zoomArg === "FitBH" || zoomArg === "FitV" || zoomArg === "FitBV") {
1079           dest = [null, {
1080             name: zoomArg
1081           }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null];
1082         } else if (zoomArg === "FitR") {
1083           if (zoomArgs.length !== 5) {
1084             console.error('PDFLinkService.setHash: Not enough parameters for "FitR".');
1085           } else {
1086             dest = [null, {
1087               name: zoomArg
1088             }, zoomArgs[1] | 0, zoomArgs[2] | 0, zoomArgs[3] | 0, zoomArgs[4] | 0];
1089           }
1090         } else {
1091           console.error(`PDFLinkService.setHash: "${zoomArg}" is not a valid zoom value.`);
1092         }
1093       }
1094       if (dest) {
1095         this.pdfViewer.scrollPageIntoView({
1096           pageNumber: pageNumber || this.page,
1097           destArray: dest,
1098           allowNegativeOffset: true
1099         });
1100       } else if (pageNumber) {
1101         this.page = pageNumber;
1102       }
1103       if (params.has("pagemode")) {
1104         this.eventBus.dispatch("pagemode", {
1105           source: this,
1106           mode: params.get("pagemode")
1107         });
1108       }
1109       if (params.has("nameddest")) {
1110         this.goToDestination(params.get("nameddest"));
1111       }
1112       if (!params.has("filename") || !params.has("filedest")) {
1113         return;
1114       }
1115       hash = params.get("filedest");
1116     }
1117     dest = unescape(hash);
1118     try {
1119       dest = JSON.parse(dest);
1120       if (!Array.isArray(dest)) {
1121         dest = dest.toString();
1122       }
1123     } catch {}
1124     if (typeof dest === "string" || PDFLinkService.#isValidExplicitDest(dest)) {
1125       this.goToDestination(dest);
1126       return;
1127     }
1128     console.error(`PDFLinkService.setHash: "${unescape(hash)}" is not a valid destination.`);
1129   }
1130   executeNamedAction(action) {
1131     if (!this.pdfDocument) {
1132       return;
1133     }
1134     switch (action) {
1135       case "GoBack":
1136         this.pdfHistory?.back();
1137         break;
1138       case "GoForward":
1139         this.pdfHistory?.forward();
1140         break;
1141       case "NextPage":
1142         this.pdfViewer.nextPage();
1143         break;
1144       case "PrevPage":
1145         this.pdfViewer.previousPage();
1146         break;
1147       case "LastPage":
1148         this.page = this.pagesCount;
1149         break;
1150       case "FirstPage":
1151         this.page = 1;
1152         break;
1153       default:
1154         break;
1155     }
1156     this.eventBus.dispatch("namedaction", {
1157       source: this,
1158       action
1159     });
1160   }
1161   async executeSetOCGState(action) {
1162     if (!this.pdfDocument) {
1163       return;
1164     }
1165     const pdfDocument = this.pdfDocument,
1166       optionalContentConfig = await this.pdfViewer.optionalContentConfigPromise;
1167     if (pdfDocument !== this.pdfDocument) {
1168       return;
1169     }
1170     optionalContentConfig.setOCGState(action);
1171     this.pdfViewer.optionalContentConfigPromise = Promise.resolve(optionalContentConfig);
1172   }
1173   static #isValidExplicitDest(dest) {
1174     if (!Array.isArray(dest) || dest.length < 2) {
1175       return false;
1176     }
1177     const [page, zoom, ...args] = dest;
1178     if (!(typeof page === "object" && Number.isInteger(page?.num) && Number.isInteger(page?.gen)) && !Number.isInteger(page)) {
1179       return false;
1180     }
1181     if (!(typeof zoom === "object" && typeof zoom?.name === "string")) {
1182       return false;
1183     }
1184     const argsLen = args.length;
1185     let allowNull = true;
1186     switch (zoom.name) {
1187       case "XYZ":
1188         if (argsLen < 2 || argsLen > 3) {
1189           return false;
1190         }
1191         break;
1192       case "Fit":
1193       case "FitB":
1194         return argsLen === 0;
1195       case "FitH":
1196       case "FitBH":
1197       case "FitV":
1198       case "FitBV":
1199         if (argsLen > 1) {
1200           return false;
1201         }
1202         break;
1203       case "FitR":
1204         if (argsLen !== 4) {
1205           return false;
1206         }
1207         allowNull = false;
1208         break;
1209       default:
1210         return false;
1211     }
1212     for (const arg of args) {
1213       if (!(typeof arg === "number" || allowNull && arg === null)) {
1214         return false;
1215       }
1216     }
1217     return true;
1218   }
1220 class SimpleLinkService extends PDFLinkService {
1221   setDocument(pdfDocument, baseUrl = null) {}
1224 ;// ./web/pdfjs.js
1225 const {
1226   AbortException,
1227   AnnotationEditorLayer,
1228   AnnotationEditorParamsType,
1229   AnnotationEditorType,
1230   AnnotationEditorUIManager,
1231   AnnotationLayer,
1232   AnnotationMode,
1233   build,
1234   ColorPicker,
1235   createValidAbsoluteUrl,
1236   DOMSVGFactory,
1237   DrawLayer,
1238   FeatureTest,
1239   fetchData,
1240   getDocument,
1241   getFilenameFromUrl,
1242   getPdfFilenameFromUrl,
1243   getXfaPageViewport,
1244   GlobalWorkerOptions,
1245   ImageKind,
1246   InvalidPDFException,
1247   isDataScheme,
1248   isPdfFile,
1249   noContextMenu,
1250   normalizeUnicode,
1251   OPS,
1252   OutputScale,
1253   PasswordResponses,
1254   PDFDataRangeTransport,
1255   PDFDateString,
1256   PDFWorker,
1257   PermissionFlag,
1258   PixelsPerInch,
1259   RenderingCancelledException,
1260   ResponseException,
1261   setLayerDimensions,
1262   shadow,
1263   stopEvent,
1264   SupportedImageMimeTypes,
1265   TextLayer,
1266   TouchManager,
1267   Util,
1268   VerbosityLevel,
1269   version,
1270   XfaLayer
1271 } = globalThis.pdfjsLib;
1273 ;// ./web/event_utils.js
1274 const WaitOnType = {
1275   EVENT: "event",
1276   TIMEOUT: "timeout"
1278 async function waitOnEventOrTimeout({
1279   target,
1280   name,
1281   delay = 0
1282 }) {
1283   if (typeof target !== "object" || !(name && typeof name === "string") || !(Number.isInteger(delay) && delay >= 0)) {
1284     throw new Error("waitOnEventOrTimeout - invalid parameters.");
1285   }
1286   const {
1287     promise,
1288     resolve
1289   } = Promise.withResolvers();
1290   const ac = new AbortController();
1291   function handler(type) {
1292     ac.abort();
1293     clearTimeout(timeout);
1294     resolve(type);
1295   }
1296   const evtMethod = target instanceof EventBus ? "_on" : "addEventListener";
1297   target[evtMethod](name, handler.bind(null, WaitOnType.EVENT), {
1298     signal: ac.signal
1299   });
1300   const timeout = setTimeout(handler.bind(null, WaitOnType.TIMEOUT), delay);
1301   return promise;
1303 class EventBus {
1304   #listeners = Object.create(null);
1305   on(eventName, listener, options = null) {
1306     this._on(eventName, listener, {
1307       external: true,
1308       once: options?.once,
1309       signal: options?.signal
1310     });
1311   }
1312   off(eventName, listener, options = null) {
1313     this._off(eventName, listener);
1314   }
1315   dispatch(eventName, data) {
1316     const eventListeners = this.#listeners[eventName];
1317     if (!eventListeners || eventListeners.length === 0) {
1318       return;
1319     }
1320     let externalListeners;
1321     for (const {
1322       listener,
1323       external,
1324       once
1325     } of eventListeners.slice(0)) {
1326       if (once) {
1327         this._off(eventName, listener);
1328       }
1329       if (external) {
1330         (externalListeners ||= []).push(listener);
1331         continue;
1332       }
1333       listener(data);
1334     }
1335     if (externalListeners) {
1336       for (const listener of externalListeners) {
1337         listener(data);
1338       }
1339       externalListeners = null;
1340     }
1341   }
1342   _on(eventName, listener, options = null) {
1343     let rmAbort = null;
1344     if (options?.signal instanceof AbortSignal) {
1345       const {
1346         signal
1347       } = options;
1348       if (signal.aborted) {
1349         console.error("Cannot use an `aborted` signal.");
1350         return;
1351       }
1352       const onAbort = () => this._off(eventName, listener);
1353       rmAbort = () => signal.removeEventListener("abort", onAbort);
1354       signal.addEventListener("abort", onAbort);
1355     }
1356     const eventListeners = this.#listeners[eventName] ||= [];
1357     eventListeners.push({
1358       listener,
1359       external: options?.external === true,
1360       once: options?.once === true,
1361       rmAbort
1362     });
1363   }
1364   _off(eventName, listener, options = null) {
1365     const eventListeners = this.#listeners[eventName];
1366     if (!eventListeners) {
1367       return;
1368     }
1369     for (let i = 0, ii = eventListeners.length; i < ii; i++) {
1370       const evt = eventListeners[i];
1371       if (evt.listener === listener) {
1372         evt.rmAbort?.();
1373         eventListeners.splice(i, 1);
1374         return;
1375       }
1376     }
1377   }
1379 class FirefoxEventBus extends EventBus {
1380   #externalServices;
1381   #globalEventNames;
1382   #isInAutomation;
1383   constructor(globalEventNames, externalServices, isInAutomation) {
1384     super();
1385     this.#globalEventNames = globalEventNames;
1386     this.#externalServices = externalServices;
1387     this.#isInAutomation = isInAutomation;
1388   }
1389   dispatch(eventName, data) {
1390     super.dispatch(eventName, data);
1391     if (this.#isInAutomation) {
1392       const detail = Object.create(null);
1393       if (data) {
1394         for (const key in data) {
1395           const value = data[key];
1396           if (key === "source") {
1397             if (value === window || value === document) {
1398               return;
1399             }
1400             continue;
1401           }
1402           detail[key] = value;
1403         }
1404       }
1405       const event = new CustomEvent(eventName, {
1406         bubbles: true,
1407         cancelable: true,
1408         detail
1409       });
1410       document.dispatchEvent(event);
1411     }
1412     if (this.#globalEventNames?.has(eventName)) {
1413       this.#externalServices.dispatchGlobalEvent({
1414         eventName,
1415         detail: data
1416       });
1417     }
1418   }
1421 ;// ./web/external_services.js
1422 class BaseExternalServices {
1423   updateFindControlState(data) {}
1424   updateFindMatchesCount(data) {}
1425   initPassiveLoading() {}
1426   reportTelemetry(data) {}
1427   async createL10n() {
1428     throw new Error("Not implemented: createL10n");
1429   }
1430   createScripting() {
1431     throw new Error("Not implemented: createScripting");
1432   }
1433   updateEditorStates(data) {
1434     throw new Error("Not implemented: updateEditorStates");
1435   }
1436   dispatchGlobalEvent(_event) {}
1439 ;// ./web/preferences.js
1441 class BasePreferences {
1442   #defaults = Object.freeze({
1443     altTextLearnMoreUrl: "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/pdf-alt-text",
1444     annotationEditorMode: 0,
1445     annotationMode: 2,
1446     cursorToolOnLoad: 0,
1447     defaultZoomDelay: 400,
1448     defaultZoomValue: "",
1449     disablePageLabels: false,
1450     enableAltText: false,
1451     enableAltTextModelDownload: true,
1452     enableGuessAltText: true,
1453     enableHighlightFloatingButton: false,
1454     enableNewAltTextWhenAddingImage: true,
1455     enablePermissions: false,
1456     enablePrintAutoRotate: true,
1457     enableScripting: true,
1458     enableSignatureEditor: false,
1459     enableUpdatedAddImage: false,
1460     externalLinkTarget: 0,
1461     highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",
1462     historyUpdateUrl: false,
1463     ignoreDestinationZoom: false,
1464     forcePageColors: false,
1465     pageColorsBackground: "Canvas",
1466     pageColorsForeground: "CanvasText",
1467     pdfBugEnabled: false,
1468     sidebarViewOnLoad: -1,
1469     scrollModeOnLoad: -1,
1470     spreadModeOnLoad: -1,
1471     textLayerMode: 1,
1472     viewOnLoad: 0,
1473     disableAutoFetch: false,
1474     disableFontFace: false,
1475     disableRange: false,
1476     disableStream: false,
1477     enableHWA: false,
1478     enableXfa: true
1479   });
1480   #initializedPromise = null;
1481   constructor() {
1482     this.#initializedPromise = this._readFromStorage(this.#defaults).then(({
1483       browserPrefs,
1484       prefs
1485     }) => {
1486       AppOptions.setAll({
1487         ...browserPrefs,
1488         ...prefs
1489       }, true);
1490     });
1491     window.addEventListener("updatedPreference", async ({
1492       detail: {
1493         name,
1494         value
1495       }
1496     }) => {
1497       await this.#initializedPromise;
1498       AppOptions.setAll({
1499         [name]: value
1500       }, true);
1501     });
1502   }
1503   async _writeToStorage(prefObj) {
1504     throw new Error("Not implemented: _writeToStorage");
1505   }
1506   async _readFromStorage(prefObj) {
1507     throw new Error("Not implemented: _readFromStorage");
1508   }
1509   async reset() {
1510     throw new Error("Please use `about:config` to change preferences.");
1511   }
1512   async set(name, value) {
1513     await this.#initializedPromise;
1514     AppOptions.setAll({
1515       [name]: value
1516     }, true);
1517     await this._writeToStorage({
1518       [name]: AppOptions.get(name)
1519     });
1520   }
1521   async get(name) {
1522     throw new Error("Not implemented: get");
1523   }
1524   get initializedPromise() {
1525     return this.#initializedPromise;
1526   }
1529 ;// ./web/l10n.js
1530 class L10n {
1531   #dir;
1532   #elements;
1533   #lang;
1534   #l10n;
1535   constructor({
1536     lang,
1537     isRTL
1538   }, l10n = null) {
1539     this.#lang = L10n.#fixupLangCode(lang);
1540     this.#l10n = l10n;
1541     this.#dir = isRTL ?? L10n.#isRTL(this.#lang) ? "rtl" : "ltr";
1542   }
1543   _setL10n(l10n) {
1544     this.#l10n = l10n;
1545   }
1546   getLanguage() {
1547     return this.#lang;
1548   }
1549   getDirection() {
1550     return this.#dir;
1551   }
1552   async get(ids, args = null, fallback) {
1553     if (Array.isArray(ids)) {
1554       ids = ids.map(id => ({
1555         id
1556       }));
1557       const messages = await this.#l10n.formatMessages(ids);
1558       return messages.map(message => message.value);
1559     }
1560     const messages = await this.#l10n.formatMessages([{
1561       id: ids,
1562       args
1563     }]);
1564     return messages[0]?.value || fallback;
1565   }
1566   async translate(element) {
1567     (this.#elements ||= new Set()).add(element);
1568     try {
1569       this.#l10n.connectRoot(element);
1570       await this.#l10n.translateRoots();
1571     } catch {}
1572   }
1573   async translateOnce(element) {
1574     try {
1575       await this.#l10n.translateElements([element]);
1576     } catch (ex) {
1577       console.error("translateOnce:", ex);
1578     }
1579   }
1580   async destroy() {
1581     if (this.#elements) {
1582       for (const element of this.#elements) {
1583         this.#l10n.disconnectRoot(element);
1584       }
1585       this.#elements.clear();
1586       this.#elements = null;
1587     }
1588     this.#l10n.pauseObserving();
1589   }
1590   pause() {
1591     this.#l10n.pauseObserving();
1592   }
1593   resume() {
1594     this.#l10n.resumeObserving();
1595   }
1596   static #fixupLangCode(langCode) {
1597     langCode = langCode?.toLowerCase() || "en-us";
1598     const PARTIAL_LANG_CODES = {
1599       en: "en-us",
1600       es: "es-es",
1601       fy: "fy-nl",
1602       ga: "ga-ie",
1603       gu: "gu-in",
1604       hi: "hi-in",
1605       hy: "hy-am",
1606       nb: "nb-no",
1607       ne: "ne-np",
1608       nn: "nn-no",
1609       pa: "pa-in",
1610       pt: "pt-pt",
1611       sv: "sv-se",
1612       zh: "zh-cn"
1613     };
1614     return PARTIAL_LANG_CODES[langCode] || langCode;
1615   }
1616   static #isRTL(lang) {
1617     const shortCode = lang.split("-", 1)[0];
1618     return ["ar", "he", "fa", "ps", "ur"].includes(shortCode);
1619   }
1621 const GenericL10n = null;
1623 ;// ./web/firefoxcom.js
1630 let viewerApp = {
1631   initialized: false
1633 function initCom(app) {
1634   viewerApp = app;
1636 class FirefoxCom {
1637   static requestAsync(action, data) {
1638     return new Promise(resolve => {
1639       this.request(action, data, resolve);
1640     });
1641   }
1642   static request(action, data, callback = null) {
1643     const request = document.createTextNode("");
1644     if (callback) {
1645       request.addEventListener("pdf.js.response", event => {
1646         const response = event.detail.response;
1647         event.target.remove();
1648         callback(response);
1649       }, {
1650         once: true
1651       });
1652     }
1653     document.documentElement.append(request);
1654     const sender = new CustomEvent("pdf.js.message", {
1655       bubbles: true,
1656       cancelable: false,
1657       detail: {
1658         action,
1659         data,
1660         responseExpected: !!callback
1661       }
1662     });
1663     request.dispatchEvent(sender);
1664   }
1666 class DownloadManager {
1667   #openBlobUrls = new WeakMap();
1668   downloadData(data, filename, contentType) {
1669     const blobUrl = URL.createObjectURL(new Blob([data], {
1670       type: contentType
1671     }));
1672     FirefoxCom.request("download", {
1673       blobUrl,
1674       originalUrl: blobUrl,
1675       filename,
1676       isAttachment: true
1677     });
1678   }
1679   openOrDownloadData(data, filename, dest = null) {
1680     const isPdfData = isPdfFile(filename);
1681     const contentType = isPdfData ? "application/pdf" : "";
1682     if (isPdfData) {
1683       let blobUrl = this.#openBlobUrls.get(data);
1684       if (!blobUrl) {
1685         blobUrl = URL.createObjectURL(new Blob([data], {
1686           type: contentType
1687         }));
1688         this.#openBlobUrls.set(data, blobUrl);
1689       }
1690       let viewerUrl = blobUrl + "#filename=" + encodeURIComponent(filename);
1691       if (dest) {
1692         viewerUrl += `&filedest=${escape(dest)}`;
1693       }
1694       try {
1695         window.open(viewerUrl);
1696         return true;
1697       } catch (ex) {
1698         console.error("openOrDownloadData:", ex);
1699         URL.revokeObjectURL(blobUrl);
1700         this.#openBlobUrls.delete(data);
1701       }
1702     }
1703     this.downloadData(data, filename, contentType);
1704     return false;
1705   }
1706   download(data, url, filename) {
1707     const blobUrl = data ? URL.createObjectURL(new Blob([data], {
1708       type: "application/pdf"
1709     })) : null;
1710     FirefoxCom.request("download", {
1711       blobUrl,
1712       originalUrl: url,
1713       filename
1714     });
1715   }
1717 class Preferences extends BasePreferences {
1718   async _readFromStorage(prefObj) {
1719     return FirefoxCom.requestAsync("getPreferences", prefObj);
1720   }
1721   async _writeToStorage(prefObj) {
1722     return FirefoxCom.requestAsync("setPreferences", prefObj);
1723   }
1725 (function listenFindEvents() {
1726   const events = ["find", "findagain", "findhighlightallchange", "findcasesensitivitychange", "findentirewordchange", "findbarclose", "finddiacriticmatchingchange"];
1727   const findLen = "find".length;
1728   const handleEvent = function ({
1729     type,
1730     detail
1731   }) {
1732     if (!viewerApp.initialized) {
1733       return;
1734     }
1735     if (type === "findbarclose") {
1736       viewerApp.eventBus.dispatch(type, {
1737         source: window
1738       });
1739       return;
1740     }
1741     viewerApp.eventBus.dispatch("find", {
1742       source: window,
1743       type: type.substring(findLen),
1744       query: detail.query,
1745       caseSensitive: !!detail.caseSensitive,
1746       entireWord: !!detail.entireWord,
1747       highlightAll: !!detail.highlightAll,
1748       findPrevious: !!detail.findPrevious,
1749       matchDiacritics: !!detail.matchDiacritics
1750     });
1751   };
1752   for (const event of events) {
1753     window.addEventListener(event, handleEvent);
1754   }
1755 })();
1756 (function listenZoomEvents() {
1757   const events = ["zoomin", "zoomout", "zoomreset"];
1758   const handleEvent = function ({
1759     type,
1760     detail
1761   }) {
1762     if (!viewerApp.initialized) {
1763       return;
1764     }
1765     if (type === "zoomreset" && viewerApp.pdfViewer.currentScaleValue === DEFAULT_SCALE_VALUE) {
1766       return;
1767     }
1768     viewerApp.eventBus.dispatch(type, {
1769       source: window
1770     });
1771   };
1772   for (const event of events) {
1773     window.addEventListener(event, handleEvent);
1774   }
1775 })();
1776 (function listenSaveEvent() {
1777   const handleEvent = function ({
1778     type,
1779     detail
1780   }) {
1781     if (!viewerApp.initialized) {
1782       return;
1783     }
1784     viewerApp.eventBus.dispatch("download", {
1785       source: window
1786     });
1787   };
1788   window.addEventListener("save", handleEvent);
1789 })();
1790 (function listenEditingEvent() {
1791   const handleEvent = function ({
1792     detail
1793   }) {
1794     if (!viewerApp.initialized) {
1795       return;
1796     }
1797     viewerApp.eventBus.dispatch("editingaction", {
1798       source: window,
1799       name: detail.name
1800     });
1801   };
1802   window.addEventListener("editingaction", handleEvent);
1803 })();
1804 class FirefoxComDataRangeTransport extends PDFDataRangeTransport {
1805   requestDataRange(begin, end) {
1806     FirefoxCom.request("requestDataRange", {
1807       begin,
1808       end
1809     });
1810   }
1811   abort() {
1812     FirefoxCom.request("abortLoading", null);
1813   }
1815 class FirefoxScripting {
1816   static async createSandbox(data) {
1817     const success = await FirefoxCom.requestAsync("createSandbox", data);
1818     if (!success) {
1819       throw new Error("Cannot create sandbox.");
1820     }
1821   }
1822   static async dispatchEventInSandbox(event) {
1823     FirefoxCom.request("dispatchEventInSandbox", event);
1824   }
1825   static async destroySandbox() {
1826     FirefoxCom.request("destroySandbox", null);
1827   }
1829 class MLManager {
1830   #abortSignal = null;
1831   #enabled = null;
1832   #eventBus = null;
1833   #ready = null;
1834   #requestResolvers = null;
1835   hasProgress = false;
1836   static #AI_ALT_TEXT_MODEL_NAME = "moz-image-to-text";
1837   constructor({
1838     altTextLearnMoreUrl,
1839     enableGuessAltText,
1840     enableAltTextModelDownload
1841   }) {
1842     this.altTextLearnMoreUrl = altTextLearnMoreUrl;
1843     this.enableAltTextModelDownload = enableAltTextModelDownload;
1844     this.enableGuessAltText = enableGuessAltText;
1845   }
1846   setEventBus(eventBus, abortSignal) {
1847     this.#eventBus = eventBus;
1848     this.#abortSignal = abortSignal;
1849     eventBus._on("enablealttextmodeldownload", ({
1850       value
1851     }) => {
1852       if (this.enableAltTextModelDownload === value) {
1853         return;
1854       }
1855       if (value) {
1856         this.downloadModel("altText");
1857       } else {
1858         this.deleteModel("altText");
1859       }
1860     }, {
1861       signal: abortSignal
1862     });
1863     eventBus._on("enableguessalttext", ({
1864       value
1865     }) => {
1866       this.toggleService("altText", value);
1867     }, {
1868       signal: abortSignal
1869     });
1870   }
1871   async isEnabledFor(name) {
1872     return this.enableGuessAltText && !!(await this.#enabled?.get(name));
1873   }
1874   isReady(name) {
1875     return this.#ready?.has(name) ?? false;
1876   }
1877   async deleteModel(name) {
1878     if (name !== "altText" || !this.enableAltTextModelDownload) {
1879       return;
1880     }
1881     this.enableAltTextModelDownload = false;
1882     this.#ready?.delete(name);
1883     this.#enabled?.delete(name);
1884     await this.toggleService("altText", false);
1885     await FirefoxCom.requestAsync("mlDelete", MLManager.#AI_ALT_TEXT_MODEL_NAME);
1886   }
1887   async loadModel(name) {
1888     if (name === "altText" && this.enableAltTextModelDownload) {
1889       await this.#loadAltTextEngine(false);
1890     }
1891   }
1892   async downloadModel(name) {
1893     if (name !== "altText" || this.enableAltTextModelDownload) {
1894       return null;
1895     }
1896     this.enableAltTextModelDownload = true;
1897     return this.#loadAltTextEngine(true);
1898   }
1899   async guess(data) {
1900     if (data?.name !== "altText") {
1901       return null;
1902     }
1903     const resolvers = this.#requestResolvers ||= new Set();
1904     const resolver = Promise.withResolvers();
1905     resolvers.add(resolver);
1906     data.service = MLManager.#AI_ALT_TEXT_MODEL_NAME;
1907     FirefoxCom.requestAsync("mlGuess", data).then(response => {
1908       if (resolvers.has(resolver)) {
1909         resolver.resolve(response);
1910         resolvers.delete(resolver);
1911       }
1912     }).catch(reason => {
1913       if (resolvers.has(resolver)) {
1914         resolver.reject(reason);
1915         resolvers.delete(resolver);
1916       }
1917     });
1918     return resolver.promise;
1919   }
1920   async #cancelAllRequests() {
1921     if (!this.#requestResolvers) {
1922       return;
1923     }
1924     for (const resolver of this.#requestResolvers) {
1925       resolver.resolve({
1926         cancel: true
1927       });
1928     }
1929     this.#requestResolvers.clear();
1930     this.#requestResolvers = null;
1931   }
1932   async toggleService(name, enabled) {
1933     if (name !== "altText" || this.enableGuessAltText === enabled) {
1934       return;
1935     }
1936     this.enableGuessAltText = enabled;
1937     if (enabled) {
1938       if (this.enableAltTextModelDownload) {
1939         await this.#loadAltTextEngine(false);
1940       }
1941     } else {
1942       this.#cancelAllRequests();
1943     }
1944   }
1945   async #loadAltTextEngine(listenToProgress) {
1946     if (this.#enabled?.has("altText")) {
1947       return;
1948     }
1949     this.#ready ||= new Set();
1950     const promise = FirefoxCom.requestAsync("loadAIEngine", {
1951       service: MLManager.#AI_ALT_TEXT_MODEL_NAME,
1952       listenToProgress
1953     }).then(ok => {
1954       if (ok) {
1955         this.#ready.add("altText");
1956       }
1957       return ok;
1958     });
1959     (this.#enabled ||= new Map()).set("altText", promise);
1960     if (listenToProgress) {
1961       const ac = new AbortController();
1962       const signal = AbortSignal.any([this.#abortSignal, ac.signal]);
1963       this.hasProgress = true;
1964       window.addEventListener("loadAIEngineProgress", ({
1965         detail
1966       }) => {
1967         this.#eventBus.dispatch("loadaiengineprogress", {
1968           source: this,
1969           detail
1970         });
1971         if (detail.finished) {
1972           ac.abort();
1973           this.hasProgress = false;
1974         }
1975       }, {
1976         signal
1977       });
1978       promise.then(ok => {
1979         if (!ok) {
1980           ac.abort();
1981           this.hasProgress = false;
1982         }
1983       });
1984     }
1985     await promise;
1986   }
1988 class ExternalServices extends BaseExternalServices {
1989   updateFindControlState(data) {
1990     FirefoxCom.request("updateFindControlState", data);
1991   }
1992   updateFindMatchesCount(data) {
1993     FirefoxCom.request("updateFindMatchesCount", data);
1994   }
1995   initPassiveLoading() {
1996     let pdfDataRangeTransport;
1997     window.addEventListener("message", function windowMessage(e) {
1998       if (e.source !== null) {
1999         console.warn("Rejected untrusted message from " + e.origin);
2000         return;
2001       }
2002       const args = e.data;
2003       if (typeof args !== "object" || !("pdfjsLoadAction" in args)) {
2004         return;
2005       }
2006       switch (args.pdfjsLoadAction) {
2007         case "supportsRangedLoading":
2008           if (args.done && !args.data) {
2009             viewerApp._documentError(null);
2010             break;
2011           }
2012           pdfDataRangeTransport = new FirefoxComDataRangeTransport(args.length, args.data, args.done, args.filename);
2013           viewerApp.open({
2014             range: pdfDataRangeTransport
2015           });
2016           break;
2017         case "range":
2018           pdfDataRangeTransport.onDataRange(args.begin, args.chunk);
2019           break;
2020         case "rangeProgress":
2021           pdfDataRangeTransport.onDataProgress(args.loaded);
2022           break;
2023         case "progressiveRead":
2024           pdfDataRangeTransport.onDataProgressiveRead(args.chunk);
2025           pdfDataRangeTransport.onDataProgress(args.loaded, args.total);
2026           break;
2027         case "progressiveDone":
2028           pdfDataRangeTransport?.onDataProgressiveDone();
2029           break;
2030         case "progress":
2031           viewerApp.progress(args.loaded / args.total);
2032           break;
2033         case "complete":
2034           if (!args.data) {
2035             viewerApp._documentError(null, {
2036               message: args.errorCode
2037             });
2038             break;
2039           }
2040           viewerApp.open({
2041             data: args.data,
2042             filename: args.filename
2043           });
2044           break;
2045       }
2046     });
2047     FirefoxCom.request("initPassiveLoading", null);
2048   }
2049   reportTelemetry(data) {
2050     FirefoxCom.request("reportTelemetry", data);
2051   }
2052   updateEditorStates(data) {
2053     FirefoxCom.request("updateEditorStates", data);
2054   }
2055   async createL10n() {
2056     await document.l10n.ready;
2057     return new L10n(AppOptions.get("localeProperties"), document.l10n);
2058   }
2059   createScripting() {
2060     return FirefoxScripting;
2061   }
2062   dispatchGlobalEvent(event) {
2063     FirefoxCom.request("dispatchGlobalEvent", event);
2064   }
2067 ;// ./web/new_alt_text_manager.js
2069 class NewAltTextManager {
2070   #boundCancel = this.#cancel.bind(this);
2071   #createAutomaticallyButton;
2072   #currentEditor = null;
2073   #cancelButton;
2074   #descriptionContainer;
2075   #dialog;
2076   #disclaimer;
2077   #downloadModel;
2078   #downloadModelDescription;
2079   #eventBus;
2080   #firstTime = false;
2081   #guessedAltText;
2082   #hasAI = null;
2083   #isEditing = null;
2084   #imagePreview;
2085   #imageData;
2086   #isAILoading = false;
2087   #wasAILoading = false;
2088   #learnMore;
2089   #notNowButton;
2090   #overlayManager;
2091   #textarea;
2092   #title;
2093   #uiManager;
2094   #previousAltText = null;
2095   constructor({
2096     descriptionContainer,
2097     dialog,
2098     imagePreview,
2099     cancelButton,
2100     disclaimer,
2101     notNowButton,
2102     saveButton,
2103     textarea,
2104     learnMore,
2105     errorCloseButton,
2106     createAutomaticallyButton,
2107     downloadModel,
2108     downloadModelDescription,
2109     title
2110   }, overlayManager, eventBus) {
2111     this.#cancelButton = cancelButton;
2112     this.#createAutomaticallyButton = createAutomaticallyButton;
2113     this.#descriptionContainer = descriptionContainer;
2114     this.#dialog = dialog;
2115     this.#disclaimer = disclaimer;
2116     this.#notNowButton = notNowButton;
2117     this.#imagePreview = imagePreview;
2118     this.#textarea = textarea;
2119     this.#learnMore = learnMore;
2120     this.#title = title;
2121     this.#downloadModel = downloadModel;
2122     this.#downloadModelDescription = downloadModelDescription;
2123     this.#overlayManager = overlayManager;
2124     this.#eventBus = eventBus;
2125     dialog.addEventListener("close", this.#close.bind(this));
2126     dialog.addEventListener("contextmenu", event => {
2127       if (event.target !== this.#textarea) {
2128         event.preventDefault();
2129       }
2130     });
2131     cancelButton.addEventListener("click", this.#boundCancel);
2132     notNowButton.addEventListener("click", this.#boundCancel);
2133     saveButton.addEventListener("click", this.#save.bind(this));
2134     errorCloseButton.addEventListener("click", () => {
2135       this.#toggleError(false);
2136     });
2137     createAutomaticallyButton.addEventListener("click", async () => {
2138       const checked = createAutomaticallyButton.getAttribute("aria-pressed") !== "true";
2139       this.#currentEditor._reportTelemetry({
2140         action: "pdfjs.image.alt_text.ai_generation_check",
2141         data: {
2142           status: checked
2143         }
2144       });
2145       if (this.#uiManager) {
2146         this.#uiManager.setPreference("enableGuessAltText", checked);
2147         await this.#uiManager.mlManager.toggleService("altText", checked);
2148       }
2149       this.#toggleGuessAltText(checked, false);
2150     });
2151     textarea.addEventListener("focus", () => {
2152       this.#wasAILoading = this.#isAILoading;
2153       this.#toggleLoading(false);
2154       this.#toggleTitleAndDisclaimer();
2155     });
2156     textarea.addEventListener("blur", () => {
2157       if (!textarea.value) {
2158         this.#toggleLoading(this.#wasAILoading);
2159       }
2160       this.#toggleTitleAndDisclaimer();
2161     });
2162     textarea.addEventListener("input", () => {
2163       this.#toggleTitleAndDisclaimer();
2164     });
2165     eventBus._on("enableguessalttext", ({
2166       value
2167     }) => {
2168       this.#toggleGuessAltText(value, false);
2169     });
2170     this.#overlayManager.register(dialog);
2171     this.#learnMore.addEventListener("click", () => {
2172       this.#currentEditor._reportTelemetry({
2173         action: "pdfjs.image.alt_text.info",
2174         data: {
2175           topic: "alt_text"
2176         }
2177       });
2178     });
2179   }
2180   #toggleLoading(value) {
2181     if (!this.#uiManager || this.#isAILoading === value) {
2182       return;
2183     }
2184     this.#isAILoading = value;
2185     this.#descriptionContainer.classList.toggle("loading", value);
2186   }
2187   #toggleError(value) {
2188     if (!this.#uiManager) {
2189       return;
2190     }
2191     this.#dialog.classList.toggle("error", value);
2192   }
2193   async #toggleGuessAltText(value, isInitial = false) {
2194     if (!this.#uiManager) {
2195       return;
2196     }
2197     this.#dialog.classList.toggle("aiDisabled", !value);
2198     this.#createAutomaticallyButton.setAttribute("aria-pressed", value);
2199     if (value) {
2200       const {
2201         altTextLearnMoreUrl
2202       } = this.#uiManager.mlManager;
2203       if (altTextLearnMoreUrl) {
2204         this.#learnMore.href = altTextLearnMoreUrl;
2205       }
2206       this.#mlGuessAltText(isInitial);
2207     } else {
2208       this.#toggleLoading(false);
2209       this.#isAILoading = false;
2210       this.#toggleTitleAndDisclaimer();
2211     }
2212   }
2213   #toggleNotNow() {
2214     this.#notNowButton.classList.toggle("hidden", !this.#firstTime);
2215     this.#cancelButton.classList.toggle("hidden", this.#firstTime);
2216   }
2217   #toggleAI(value) {
2218     if (!this.#uiManager || this.#hasAI === value) {
2219       return;
2220     }
2221     this.#hasAI = value;
2222     this.#dialog.classList.toggle("noAi", !value);
2223     this.#toggleTitleAndDisclaimer();
2224   }
2225   #toggleTitleAndDisclaimer() {
2226     const visible = this.#isAILoading || this.#guessedAltText && this.#guessedAltText === this.#textarea.value;
2227     this.#disclaimer.hidden = !visible;
2228     const isEditing = this.#isAILoading || !!this.#textarea.value;
2229     if (this.#isEditing === isEditing) {
2230       return;
2231     }
2232     this.#isEditing = isEditing;
2233     this.#title.setAttribute("data-l10n-id", isEditing ? "pdfjs-editor-new-alt-text-dialog-edit-label" : "pdfjs-editor-new-alt-text-dialog-add-label");
2234   }
2235   async #mlGuessAltText(isInitial) {
2236     if (this.#isAILoading) {
2237       return;
2238     }
2239     if (this.#textarea.value) {
2240       return;
2241     }
2242     if (isInitial && this.#previousAltText !== null) {
2243       return;
2244     }
2245     this.#guessedAltText = this.#currentEditor.guessedAltText;
2246     if (this.#previousAltText === null && this.#guessedAltText) {
2247       this.#addAltText(this.#guessedAltText);
2248       return;
2249     }
2250     this.#toggleLoading(true);
2251     this.#toggleTitleAndDisclaimer();
2252     let hasError = false;
2253     try {
2254       const altText = await this.#currentEditor.mlGuessAltText(this.#imageData, false);
2255       if (altText) {
2256         this.#guessedAltText = altText;
2257         this.#wasAILoading = this.#isAILoading;
2258         if (this.#isAILoading) {
2259           this.#addAltText(altText);
2260         }
2261       }
2262     } catch (e) {
2263       console.error(e);
2264       hasError = true;
2265     }
2266     this.#toggleLoading(false);
2267     this.#toggleTitleAndDisclaimer();
2268     if (hasError && this.#uiManager) {
2269       this.#toggleError(true);
2270     }
2271   }
2272   #addAltText(altText) {
2273     if (!this.#uiManager || this.#textarea.value) {
2274       return;
2275     }
2276     this.#textarea.value = altText;
2277     this.#toggleTitleAndDisclaimer();
2278   }
2279   #setProgress() {
2280     this.#downloadModel.classList.toggle("hidden", false);
2281     const callback = async ({
2282       detail: {
2283         finished,
2284         total,
2285         totalLoaded
2286       }
2287     }) => {
2288       const ONE_MEGA_BYTES = 1e6;
2289       totalLoaded = Math.min(0.99 * total, totalLoaded);
2290       const totalSize = this.#downloadModelDescription.ariaValueMax = Math.round(total / ONE_MEGA_BYTES);
2291       const downloadedSize = this.#downloadModelDescription.ariaValueNow = Math.round(totalLoaded / ONE_MEGA_BYTES);
2292       this.#downloadModelDescription.setAttribute("data-l10n-args", JSON.stringify({
2293         totalSize,
2294         downloadedSize
2295       }));
2296       if (!finished) {
2297         return;
2298       }
2299       this.#eventBus._off("loadaiengineprogress", callback);
2300       this.#downloadModel.classList.toggle("hidden", true);
2301       this.#toggleAI(true);
2302       if (!this.#uiManager) {
2303         return;
2304       }
2305       const {
2306         mlManager
2307       } = this.#uiManager;
2308       mlManager.toggleService("altText", true);
2309       this.#toggleGuessAltText(await mlManager.isEnabledFor("altText"), true);
2310     };
2311     this.#eventBus._on("loadaiengineprogress", callback);
2312   }
2313   async editAltText(uiManager, editor, firstTime) {
2314     if (this.#currentEditor || !editor) {
2315       return;
2316     }
2317     if (firstTime && editor.hasAltTextData()) {
2318       editor.altTextFinish();
2319       return;
2320     }
2321     this.#firstTime = firstTime;
2322     let {
2323       mlManager
2324     } = uiManager;
2325     let hasAI = !!mlManager;
2326     this.#toggleTitleAndDisclaimer();
2327     if (mlManager && !mlManager.isReady("altText")) {
2328       hasAI = false;
2329       if (mlManager.hasProgress) {
2330         this.#setProgress();
2331       } else {
2332         mlManager = null;
2333       }
2334     } else {
2335       this.#downloadModel.classList.toggle("hidden", true);
2336     }
2337     const isAltTextEnabledPromise = mlManager?.isEnabledFor("altText");
2338     this.#currentEditor = editor;
2339     this.#uiManager = uiManager;
2340     this.#uiManager.removeEditListeners();
2341     ({
2342       altText: this.#previousAltText
2343     } = editor.altTextData);
2344     this.#textarea.value = this.#previousAltText ?? "";
2345     const AI_MAX_IMAGE_DIMENSION = 224;
2346     const MAX_PREVIEW_DIMENSION = 180;
2347     let canvas, width, height;
2348     if (mlManager) {
2349       ({
2350         canvas,
2351         width,
2352         height,
2353         imageData: this.#imageData
2354       } = editor.copyCanvas(AI_MAX_IMAGE_DIMENSION, MAX_PREVIEW_DIMENSION, true));
2355       if (hasAI) {
2356         this.#toggleGuessAltText(await isAltTextEnabledPromise, true);
2357       }
2358     } else {
2359       ({
2360         canvas,
2361         width,
2362         height
2363       } = editor.copyCanvas(AI_MAX_IMAGE_DIMENSION, MAX_PREVIEW_DIMENSION, false));
2364     }
2365     canvas.setAttribute("role", "presentation");
2366     const {
2367       style
2368     } = canvas;
2369     style.width = `${width}px`;
2370     style.height = `${height}px`;
2371     this.#imagePreview.append(canvas);
2372     this.#toggleNotNow();
2373     this.#toggleAI(hasAI);
2374     this.#toggleError(false);
2375     try {
2376       await this.#overlayManager.open(this.#dialog);
2377     } catch (ex) {
2378       this.#close();
2379       throw ex;
2380     }
2381   }
2382   #cancel() {
2383     this.#currentEditor.altTextData = {
2384       cancel: true
2385     };
2386     const altText = this.#textarea.value.trim();
2387     this.#currentEditor._reportTelemetry({
2388       action: "pdfjs.image.alt_text.dismiss",
2389       data: {
2390         alt_text_type: altText ? "present" : "empty",
2391         flow: this.#firstTime ? "image_add" : "alt_text_edit"
2392       }
2393     });
2394     this.#currentEditor._reportTelemetry({
2395       action: "pdfjs.image.image_added",
2396       data: {
2397         alt_text_modal: true,
2398         alt_text_type: "skipped"
2399       }
2400     });
2401     this.#finish();
2402   }
2403   #finish() {
2404     if (this.#overlayManager.active === this.#dialog) {
2405       this.#overlayManager.close(this.#dialog);
2406     }
2407   }
2408   #close() {
2409     const canvas = this.#imagePreview.firstChild;
2410     canvas.remove();
2411     canvas.width = canvas.height = 0;
2412     this.#imageData = null;
2413     this.#toggleLoading(false);
2414     this.#uiManager?.addEditListeners();
2415     this.#currentEditor.altTextFinish();
2416     this.#uiManager?.setSelected(this.#currentEditor);
2417     this.#currentEditor = null;
2418     this.#uiManager = null;
2419   }
2420   #extractWords(text) {
2421     return new Set(text.toLowerCase().split(/[^\p{L}\p{N}]+/gu).filter(x => !!x));
2422   }
2423   #save() {
2424     const altText = this.#textarea.value.trim();
2425     this.#currentEditor.altTextData = {
2426       altText,
2427       decorative: false
2428     };
2429     this.#currentEditor.altTextData.guessedAltText = this.#guessedAltText;
2430     if (this.#guessedAltText && this.#guessedAltText !== altText) {
2431       const guessedWords = this.#extractWords(this.#guessedAltText);
2432       const words = this.#extractWords(altText);
2433       this.#currentEditor._reportTelemetry({
2434         action: "pdfjs.image.alt_text.user_edit",
2435         data: {
2436           total_words: guessedWords.size,
2437           words_removed: guessedWords.difference(words).size,
2438           words_added: words.difference(guessedWords).size
2439         }
2440       });
2441     }
2442     this.#currentEditor._reportTelemetry({
2443       action: "pdfjs.image.image_added",
2444       data: {
2445         alt_text_modal: true,
2446         alt_text_type: altText ? "present" : "empty"
2447       }
2448     });
2449     this.#currentEditor._reportTelemetry({
2450       action: "pdfjs.image.alt_text.save",
2451       data: {
2452         alt_text_type: altText ? "present" : "empty",
2453         flow: this.#firstTime ? "image_add" : "alt_text_edit"
2454       }
2455     });
2456     this.#finish();
2457   }
2458   destroy() {
2459     this.#uiManager = null;
2460     this.#finish();
2461   }
2463 class ImageAltTextSettings {
2464   #aiModelSettings;
2465   #createModelButton;
2466   #downloadModelButton;
2467   #dialog;
2468   #eventBus;
2469   #mlManager;
2470   #overlayManager;
2471   #showAltTextDialogButton;
2472   constructor({
2473     dialog,
2474     createModelButton,
2475     aiModelSettings,
2476     learnMore,
2477     closeButton,
2478     deleteModelButton,
2479     downloadModelButton,
2480     showAltTextDialogButton
2481   }, overlayManager, eventBus, mlManager) {
2482     this.#dialog = dialog;
2483     this.#aiModelSettings = aiModelSettings;
2484     this.#createModelButton = createModelButton;
2485     this.#downloadModelButton = downloadModelButton;
2486     this.#showAltTextDialogButton = showAltTextDialogButton;
2487     this.#overlayManager = overlayManager;
2488     this.#eventBus = eventBus;
2489     this.#mlManager = mlManager;
2490     const {
2491       altTextLearnMoreUrl
2492     } = mlManager;
2493     if (altTextLearnMoreUrl) {
2494       learnMore.href = altTextLearnMoreUrl;
2495     }
2496     dialog.addEventListener("contextmenu", noContextMenu);
2497     createModelButton.addEventListener("click", async e => {
2498       const checked = this.#togglePref("enableGuessAltText", e);
2499       await mlManager.toggleService("altText", checked);
2500       this.#reportTelemetry({
2501         type: "stamp",
2502         action: "pdfjs.image.alt_text.settings_ai_generation_check",
2503         data: {
2504           status: checked
2505         }
2506       });
2507     });
2508     showAltTextDialogButton.addEventListener("click", e => {
2509       const checked = this.#togglePref("enableNewAltTextWhenAddingImage", e);
2510       this.#reportTelemetry({
2511         type: "stamp",
2512         action: "pdfjs.image.alt_text.settings_edit_alt_text_check",
2513         data: {
2514           status: checked
2515         }
2516       });
2517     });
2518     deleteModelButton.addEventListener("click", this.#delete.bind(this, true));
2519     downloadModelButton.addEventListener("click", this.#download.bind(this, true));
2520     closeButton.addEventListener("click", this.#finish.bind(this));
2521     learnMore.addEventListener("click", () => {
2522       this.#reportTelemetry({
2523         type: "stamp",
2524         action: "pdfjs.image.alt_text.info",
2525         data: {
2526           topic: "ai_generation"
2527         }
2528       });
2529     });
2530     eventBus._on("enablealttextmodeldownload", ({
2531       value
2532     }) => {
2533       if (value) {
2534         this.#download(false);
2535       } else {
2536         this.#delete(false);
2537       }
2538     });
2539     this.#overlayManager.register(dialog);
2540   }
2541   #reportTelemetry(data) {
2542     this.#eventBus.dispatch("reporttelemetry", {
2543       source: this,
2544       details: {
2545         type: "editing",
2546         data
2547       }
2548     });
2549   }
2550   async #download(isFromUI = false) {
2551     if (isFromUI) {
2552       this.#downloadModelButton.disabled = true;
2553       const span = this.#downloadModelButton.firstChild;
2554       span.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-settings-downloading-model-button");
2555       await this.#mlManager.downloadModel("altText");
2556       span.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-settings-download-model-button");
2557       this.#createModelButton.disabled = false;
2558       this.#setPref("enableGuessAltText", true);
2559       this.#mlManager.toggleService("altText", true);
2560       this.#setPref("enableAltTextModelDownload", true);
2561       this.#downloadModelButton.disabled = false;
2562     }
2563     this.#aiModelSettings.classList.toggle("download", false);
2564     this.#createModelButton.setAttribute("aria-pressed", true);
2565   }
2566   async #delete(isFromUI = false) {
2567     if (isFromUI) {
2568       await this.#mlManager.deleteModel("altText");
2569       this.#setPref("enableGuessAltText", false);
2570       this.#setPref("enableAltTextModelDownload", false);
2571     }
2572     this.#aiModelSettings.classList.toggle("download", true);
2573     this.#createModelButton.disabled = true;
2574     this.#createModelButton.setAttribute("aria-pressed", false);
2575   }
2576   async open({
2577     enableGuessAltText,
2578     enableNewAltTextWhenAddingImage
2579   }) {
2580     const {
2581       enableAltTextModelDownload
2582     } = this.#mlManager;
2583     this.#createModelButton.disabled = !enableAltTextModelDownload;
2584     this.#createModelButton.setAttribute("aria-pressed", enableAltTextModelDownload && enableGuessAltText);
2585     this.#showAltTextDialogButton.setAttribute("aria-pressed", enableNewAltTextWhenAddingImage);
2586     this.#aiModelSettings.classList.toggle("download", !enableAltTextModelDownload);
2587     await this.#overlayManager.open(this.#dialog);
2588     this.#reportTelemetry({
2589       type: "stamp",
2590       action: "pdfjs.image.alt_text.settings_displayed"
2591     });
2592   }
2593   #togglePref(name, {
2594     target
2595   }) {
2596     const checked = target.getAttribute("aria-pressed") !== "true";
2597     this.#setPref(name, checked);
2598     target.setAttribute("aria-pressed", checked);
2599     return checked;
2600   }
2601   #setPref(name, value) {
2602     this.#eventBus.dispatch("setpreference", {
2603       source: this,
2604       name,
2605       value
2606     });
2607   }
2608   #finish() {
2609     if (this.#overlayManager.active === this.#dialog) {
2610       this.#overlayManager.close(this.#dialog);
2611     }
2612   }
2615 ;// ./web/alt_text_manager.js
2617 class AltTextManager {
2618   #clickAC = null;
2619   #currentEditor = null;
2620   #cancelButton;
2621   #dialog;
2622   #eventBus;
2623   #hasUsedPointer = false;
2624   #optionDescription;
2625   #optionDecorative;
2626   #overlayManager;
2627   #saveButton;
2628   #textarea;
2629   #uiManager;
2630   #previousAltText = null;
2631   #resizeAC = null;
2632   #svgElement = null;
2633   #rectElement = null;
2634   #container;
2635   #telemetryData = null;
2636   constructor({
2637     dialog,
2638     optionDescription,
2639     optionDecorative,
2640     textarea,
2641     cancelButton,
2642     saveButton
2643   }, container, overlayManager, eventBus) {
2644     this.#dialog = dialog;
2645     this.#optionDescription = optionDescription;
2646     this.#optionDecorative = optionDecorative;
2647     this.#textarea = textarea;
2648     this.#cancelButton = cancelButton;
2649     this.#saveButton = saveButton;
2650     this.#overlayManager = overlayManager;
2651     this.#eventBus = eventBus;
2652     this.#container = container;
2653     const onUpdateUIState = this.#updateUIState.bind(this);
2654     dialog.addEventListener("close", this.#close.bind(this));
2655     dialog.addEventListener("contextmenu", event => {
2656       if (event.target !== this.#textarea) {
2657         event.preventDefault();
2658       }
2659     });
2660     cancelButton.addEventListener("click", this.#finish.bind(this));
2661     saveButton.addEventListener("click", this.#save.bind(this));
2662     optionDescription.addEventListener("change", onUpdateUIState);
2663     optionDecorative.addEventListener("change", onUpdateUIState);
2664     this.#overlayManager.register(dialog);
2665   }
2666   #createSVGElement() {
2667     if (this.#svgElement) {
2668       return;
2669     }
2670     const svgFactory = new DOMSVGFactory();
2671     const svg = this.#svgElement = svgFactory.createElement("svg");
2672     svg.setAttribute("width", "0");
2673     svg.setAttribute("height", "0");
2674     const defs = svgFactory.createElement("defs");
2675     svg.append(defs);
2676     const mask = svgFactory.createElement("mask");
2677     defs.append(mask);
2678     mask.setAttribute("id", "alttext-manager-mask");
2679     mask.setAttribute("maskContentUnits", "objectBoundingBox");
2680     let rect = svgFactory.createElement("rect");
2681     mask.append(rect);
2682     rect.setAttribute("fill", "white");
2683     rect.setAttribute("width", "1");
2684     rect.setAttribute("height", "1");
2685     rect.setAttribute("x", "0");
2686     rect.setAttribute("y", "0");
2687     rect = this.#rectElement = svgFactory.createElement("rect");
2688     mask.append(rect);
2689     rect.setAttribute("fill", "black");
2690     this.#dialog.append(svg);
2691   }
2692   async editAltText(uiManager, editor) {
2693     if (this.#currentEditor || !editor) {
2694       return;
2695     }
2696     this.#createSVGElement();
2697     this.#hasUsedPointer = false;
2698     this.#clickAC = new AbortController();
2699     const clickOpts = {
2700         signal: this.#clickAC.signal
2701       },
2702       onClick = this.#onClick.bind(this);
2703     for (const element of [this.#optionDescription, this.#optionDecorative, this.#textarea, this.#saveButton, this.#cancelButton]) {
2704       element.addEventListener("click", onClick, clickOpts);
2705     }
2706     const {
2707       altText,
2708       decorative
2709     } = editor.altTextData;
2710     if (decorative === true) {
2711       this.#optionDecorative.checked = true;
2712       this.#optionDescription.checked = false;
2713     } else {
2714       this.#optionDecorative.checked = false;
2715       this.#optionDescription.checked = true;
2716     }
2717     this.#previousAltText = this.#textarea.value = altText?.trim() || "";
2718     this.#updateUIState();
2719     this.#currentEditor = editor;
2720     this.#uiManager = uiManager;
2721     this.#uiManager.removeEditListeners();
2722     this.#resizeAC = new AbortController();
2723     this.#eventBus._on("resize", this.#setPosition.bind(this), {
2724       signal: this.#resizeAC.signal
2725     });
2726     try {
2727       await this.#overlayManager.open(this.#dialog);
2728       this.#setPosition();
2729     } catch (ex) {
2730       this.#close();
2731       throw ex;
2732     }
2733   }
2734   #setPosition() {
2735     if (!this.#currentEditor) {
2736       return;
2737     }
2738     const dialog = this.#dialog;
2739     const {
2740       style
2741     } = dialog;
2742     const {
2743       x: containerX,
2744       y: containerY,
2745       width: containerW,
2746       height: containerH
2747     } = this.#container.getBoundingClientRect();
2748     const {
2749       innerWidth: windowW,
2750       innerHeight: windowH
2751     } = window;
2752     const {
2753       width: dialogW,
2754       height: dialogH
2755     } = dialog.getBoundingClientRect();
2756     const {
2757       x,
2758       y,
2759       width,
2760       height
2761     } = this.#currentEditor.getClientDimensions();
2762     const MARGIN = 10;
2763     const isLTR = this.#uiManager.direction === "ltr";
2764     const xs = Math.max(x, containerX);
2765     const xe = Math.min(x + width, containerX + containerW);
2766     const ys = Math.max(y, containerY);
2767     const ye = Math.min(y + height, containerY + containerH);
2768     this.#rectElement.setAttribute("width", `${(xe - xs) / windowW}`);
2769     this.#rectElement.setAttribute("height", `${(ye - ys) / windowH}`);
2770     this.#rectElement.setAttribute("x", `${xs / windowW}`);
2771     this.#rectElement.setAttribute("y", `${ys / windowH}`);
2772     let left = null;
2773     let top = Math.max(y, 0);
2774     top += Math.min(windowH - (top + dialogH), 0);
2775     if (isLTR) {
2776       if (x + width + MARGIN + dialogW < windowW) {
2777         left = x + width + MARGIN;
2778       } else if (x > dialogW + MARGIN) {
2779         left = x - dialogW - MARGIN;
2780       }
2781     } else if (x > dialogW + MARGIN) {
2782       left = x - dialogW - MARGIN;
2783     } else if (x + width + MARGIN + dialogW < windowW) {
2784       left = x + width + MARGIN;
2785     }
2786     if (left === null) {
2787       top = null;
2788       left = Math.max(x, 0);
2789       left += Math.min(windowW - (left + dialogW), 0);
2790       if (y > dialogH + MARGIN) {
2791         top = y - dialogH - MARGIN;
2792       } else if (y + height + MARGIN + dialogH < windowH) {
2793         top = y + height + MARGIN;
2794       }
2795     }
2796     if (top !== null) {
2797       dialog.classList.add("positioned");
2798       if (isLTR) {
2799         style.left = `${left}px`;
2800       } else {
2801         style.right = `${windowW - left - dialogW}px`;
2802       }
2803       style.top = `${top}px`;
2804     } else {
2805       dialog.classList.remove("positioned");
2806       style.left = "";
2807       style.top = "";
2808     }
2809   }
2810   #finish() {
2811     if (this.#overlayManager.active === this.#dialog) {
2812       this.#overlayManager.close(this.#dialog);
2813     }
2814   }
2815   #close() {
2816     this.#currentEditor._reportTelemetry(this.#telemetryData || {
2817       action: "alt_text_cancel",
2818       alt_text_keyboard: !this.#hasUsedPointer
2819     });
2820     this.#telemetryData = null;
2821     this.#removeOnClickListeners();
2822     this.#uiManager?.addEditListeners();
2823     this.#resizeAC?.abort();
2824     this.#resizeAC = null;
2825     this.#currentEditor.altTextFinish();
2826     this.#currentEditor = null;
2827     this.#uiManager = null;
2828   }
2829   #updateUIState() {
2830     this.#textarea.disabled = this.#optionDecorative.checked;
2831   }
2832   #save() {
2833     const altText = this.#textarea.value.trim();
2834     const decorative = this.#optionDecorative.checked;
2835     this.#currentEditor.altTextData = {
2836       altText,
2837       decorative
2838     };
2839     this.#telemetryData = {
2840       action: "alt_text_save",
2841       alt_text_description: !!altText,
2842       alt_text_edit: !!this.#previousAltText && this.#previousAltText !== altText,
2843       alt_text_decorative: decorative,
2844       alt_text_keyboard: !this.#hasUsedPointer
2845     };
2846     this.#finish();
2847   }
2848   #onClick(evt) {
2849     if (evt.detail === 0) {
2850       return;
2851     }
2852     this.#hasUsedPointer = true;
2853     this.#removeOnClickListeners();
2854   }
2855   #removeOnClickListeners() {
2856     this.#clickAC?.abort();
2857     this.#clickAC = null;
2858   }
2859   destroy() {
2860     this.#uiManager = null;
2861     this.#finish();
2862     this.#svgElement?.remove();
2863     this.#svgElement = this.#rectElement = null;
2864   }
2867 ;// ./web/annotation_editor_params.js
2869 class AnnotationEditorParams {
2870   constructor(options, eventBus) {
2871     this.eventBus = eventBus;
2872     this.#bindListeners(options);
2873   }
2874   #bindListeners({
2875     editorFreeTextFontSize,
2876     editorFreeTextColor,
2877     editorInkColor,
2878     editorInkThickness,
2879     editorInkOpacity,
2880     editorStampAddImage,
2881     editorFreeHighlightThickness,
2882     editorHighlightShowAll,
2883     editorSignatureAddSignature
2884   }) {
2885     const {
2886       eventBus
2887     } = this;
2888     const dispatchEvent = (typeStr, value) => {
2889       eventBus.dispatch("switchannotationeditorparams", {
2890         source: this,
2891         type: AnnotationEditorParamsType[typeStr],
2892         value
2893       });
2894     };
2895     editorFreeTextFontSize.addEventListener("input", function () {
2896       dispatchEvent("FREETEXT_SIZE", this.valueAsNumber);
2897     });
2898     editorFreeTextColor.addEventListener("input", function () {
2899       dispatchEvent("FREETEXT_COLOR", this.value);
2900     });
2901     editorInkColor.addEventListener("input", function () {
2902       dispatchEvent("INK_COLOR", this.value);
2903     });
2904     editorInkThickness.addEventListener("input", function () {
2905       dispatchEvent("INK_THICKNESS", this.valueAsNumber);
2906     });
2907     editorInkOpacity.addEventListener("input", function () {
2908       dispatchEvent("INK_OPACITY", this.valueAsNumber);
2909     });
2910     editorStampAddImage.addEventListener("click", () => {
2911       eventBus.dispatch("reporttelemetry", {
2912         source: this,
2913         details: {
2914           type: "editing",
2915           data: {
2916             action: "pdfjs.image.add_image_click"
2917           }
2918         }
2919       });
2920       dispatchEvent("CREATE");
2921     });
2922     editorFreeHighlightThickness.addEventListener("input", function () {
2923       dispatchEvent("HIGHLIGHT_THICKNESS", this.valueAsNumber);
2924     });
2925     editorHighlightShowAll.addEventListener("click", function () {
2926       const checked = this.getAttribute("aria-pressed") === "true";
2927       this.setAttribute("aria-pressed", !checked);
2928       dispatchEvent("HIGHLIGHT_SHOW_ALL", !checked);
2929     });
2930     editorSignatureAddSignature.addEventListener("click", () => {
2931       dispatchEvent("CREATE");
2932     });
2933     eventBus._on("annotationeditorparamschanged", evt => {
2934       for (const [type, value] of evt.details) {
2935         switch (type) {
2936           case AnnotationEditorParamsType.FREETEXT_SIZE:
2937             editorFreeTextFontSize.value = value;
2938             break;
2939           case AnnotationEditorParamsType.FREETEXT_COLOR:
2940             editorFreeTextColor.value = value;
2941             break;
2942           case AnnotationEditorParamsType.INK_COLOR:
2943             editorInkColor.value = value;
2944             break;
2945           case AnnotationEditorParamsType.INK_THICKNESS:
2946             editorInkThickness.value = value;
2947             break;
2948           case AnnotationEditorParamsType.INK_OPACITY:
2949             editorInkOpacity.value = value;
2950             break;
2951           case AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR:
2952             eventBus.dispatch("mainhighlightcolorpickerupdatecolor", {
2953               source: this,
2954               value
2955             });
2956             break;
2957           case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS:
2958             editorFreeHighlightThickness.value = value;
2959             break;
2960           case AnnotationEditorParamsType.HIGHLIGHT_FREE:
2961             editorFreeHighlightThickness.disabled = !value;
2962             break;
2963           case AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL:
2964             editorHighlightShowAll.setAttribute("aria-pressed", value);
2965             break;
2966         }
2967       }
2968     });
2969   }
2972 ;// ./web/caret_browsing.js
2973 const PRECISION = 1e-1;
2974 class CaretBrowsingMode {
2975   #mainContainer;
2976   #toolBarHeight = 0;
2977   #viewerContainer;
2978   constructor(abortSignal, mainContainer, viewerContainer, toolbarContainer) {
2979     this.#mainContainer = mainContainer;
2980     this.#viewerContainer = viewerContainer;
2981     if (!toolbarContainer) {
2982       return;
2983     }
2984     this.#toolBarHeight = toolbarContainer.getBoundingClientRect().height;
2985     const toolbarObserver = new ResizeObserver(entries => {
2986       for (const entry of entries) {
2987         if (entry.target === toolbarContainer) {
2988           this.#toolBarHeight = Math.floor(entry.borderBoxSize[0].blockSize);
2989           break;
2990         }
2991       }
2992     });
2993     toolbarObserver.observe(toolbarContainer);
2994     abortSignal.addEventListener("abort", () => toolbarObserver.disconnect(), {
2995       once: true
2996     });
2997   }
2998   #isOnSameLine(rect1, rect2) {
2999     const top1 = rect1.y;
3000     const bot1 = rect1.bottom;
3001     const mid1 = rect1.y + rect1.height / 2;
3002     const top2 = rect2.y;
3003     const bot2 = rect2.bottom;
3004     const mid2 = rect2.y + rect2.height / 2;
3005     return top1 <= mid2 && mid2 <= bot1 || top2 <= mid1 && mid1 <= bot2;
3006   }
3007   #isUnderOver(rect, x, y, isUp) {
3008     const midY = rect.y + rect.height / 2;
3009     return (isUp ? y >= midY : y <= midY) && rect.x - PRECISION <= x && x <= rect.right + PRECISION;
3010   }
3011   #isVisible(rect) {
3012     return rect.top >= this.#toolBarHeight && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);
3013   }
3014   #getCaretPosition(selection, isUp) {
3015     const {
3016       focusNode,
3017       focusOffset
3018     } = selection;
3019     const range = document.createRange();
3020     range.setStart(focusNode, focusOffset);
3021     range.setEnd(focusNode, focusOffset);
3022     const rect = range.getBoundingClientRect();
3023     return [rect.x, isUp ? rect.top : rect.bottom];
3024   }
3025   static #caretPositionFromPoint(x, y) {
3026     return document.caretPositionFromPoint(x, y);
3027   }
3028   #setCaretPositionHelper(selection, caretX, select, element, rect) {
3029     rect ||= element.getBoundingClientRect();
3030     if (caretX <= rect.x + PRECISION) {
3031       if (select) {
3032         selection.extend(element.firstChild, 0);
3033       } else {
3034         selection.setPosition(element.firstChild, 0);
3035       }
3036       return;
3037     }
3038     if (rect.right - PRECISION <= caretX) {
3039       const {
3040         lastChild
3041       } = element;
3042       if (select) {
3043         selection.extend(lastChild, lastChild.length);
3044       } else {
3045         selection.setPosition(lastChild, lastChild.length);
3046       }
3047       return;
3048     }
3049     const midY = rect.y + rect.height / 2;
3050     let caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY);
3051     let parentElement = caretPosition.offsetNode?.parentElement;
3052     if (parentElement && parentElement !== element) {
3053       const elementsAtPoint = document.elementsFromPoint(caretX, midY);
3054       const savedVisibilities = [];
3055       for (const el of elementsAtPoint) {
3056         if (el === element) {
3057           break;
3058         }
3059         const {
3060           style
3061         } = el;
3062         savedVisibilities.push([el, style.visibility]);
3063         style.visibility = "hidden";
3064       }
3065       caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY);
3066       parentElement = caretPosition.offsetNode?.parentElement;
3067       for (const [el, visibility] of savedVisibilities) {
3068         el.style.visibility = visibility;
3069       }
3070     }
3071     if (parentElement !== element) {
3072       if (select) {
3073         selection.extend(element.firstChild, 0);
3074       } else {
3075         selection.setPosition(element.firstChild, 0);
3076       }
3077       return;
3078     }
3079     if (select) {
3080       selection.extend(caretPosition.offsetNode, caretPosition.offset);
3081     } else {
3082       selection.setPosition(caretPosition.offsetNode, caretPosition.offset);
3083     }
3084   }
3085   #setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX) {
3086     if (this.#isVisible(newLineElementRect)) {
3087       this.#setCaretPositionHelper(selection, caretX, select, newLineElement, newLineElementRect);
3088       return;
3089     }
3090     this.#mainContainer.addEventListener("scrollend", this.#setCaretPositionHelper.bind(this, selection, caretX, select, newLineElement, null), {
3091       once: true
3092     });
3093     newLineElement.scrollIntoView();
3094   }
3095   #getNodeOnNextPage(textLayer, isUp) {
3096     while (true) {
3097       const page = textLayer.closest(".page");
3098       const pageNumber = parseInt(page.getAttribute("data-page-number"));
3099       const nextPage = isUp ? pageNumber - 1 : pageNumber + 1;
3100       textLayer = this.#viewerContainer.querySelector(`.page[data-page-number="${nextPage}"] .textLayer`);
3101       if (!textLayer) {
3102         return null;
3103       }
3104       const walker = document.createTreeWalker(textLayer, NodeFilter.SHOW_TEXT);
3105       const node = isUp ? walker.lastChild() : walker.firstChild();
3106       if (node) {
3107         return node;
3108       }
3109     }
3110   }
3111   moveCaret(isUp, select) {
3112     const selection = document.getSelection();
3113     if (selection.rangeCount === 0) {
3114       return;
3115     }
3116     const {
3117       focusNode
3118     } = selection;
3119     const focusElement = focusNode.nodeType !== Node.ELEMENT_NODE ? focusNode.parentElement : focusNode;
3120     const root = focusElement.closest(".textLayer");
3121     if (!root) {
3122       return;
3123     }
3124     const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
3125     walker.currentNode = focusNode;
3126     const focusRect = focusElement.getBoundingClientRect();
3127     let newLineElement = null;
3128     const nodeIterator = (isUp ? walker.previousSibling : walker.nextSibling).bind(walker);
3129     while (nodeIterator()) {
3130       const element = walker.currentNode.parentElement;
3131       if (!this.#isOnSameLine(focusRect, element.getBoundingClientRect())) {
3132         newLineElement = element;
3133         break;
3134       }
3135     }
3136     if (!newLineElement) {
3137       const node = this.#getNodeOnNextPage(root, isUp);
3138       if (!node) {
3139         return;
3140       }
3141       if (select) {
3142         const lastNode = (isUp ? walker.firstChild() : walker.lastChild()) || focusNode;
3143         selection.extend(lastNode, isUp ? 0 : lastNode.length);
3144         const range = document.createRange();
3145         range.setStart(node, isUp ? node.length : 0);
3146         range.setEnd(node, isUp ? node.length : 0);
3147         selection.addRange(range);
3148         return;
3149       }
3150       const [caretX] = this.#getCaretPosition(selection, isUp);
3151       const {
3152         parentElement
3153       } = node;
3154       this.#setCaretPosition(select, selection, parentElement, parentElement.getBoundingClientRect(), caretX);
3155       return;
3156     }
3157     const [caretX, caretY] = this.#getCaretPosition(selection, isUp);
3158     const newLineElementRect = newLineElement.getBoundingClientRect();
3159     if (this.#isUnderOver(newLineElementRect, caretX, caretY, isUp)) {
3160       this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX);
3161       return;
3162     }
3163     while (nodeIterator()) {
3164       const element = walker.currentNode.parentElement;
3165       const elementRect = element.getBoundingClientRect();
3166       if (!this.#isOnSameLine(newLineElementRect, elementRect)) {
3167         break;
3168       }
3169       if (this.#isUnderOver(elementRect, caretX, caretY, isUp)) {
3170         this.#setCaretPosition(select, selection, element, elementRect, caretX);
3171         return;
3172       }
3173     }
3174     this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX);
3175   }
3178 ;// ./web/editor_undo_bar.js
3180 class EditorUndoBar {
3181   #closeButton = null;
3182   #container;
3183   #eventBus = null;
3184   #focusTimeout = null;
3185   #initController = null;
3186   isOpen = false;
3187   #message;
3188   #showController = null;
3189   #undoButton;
3190   static #l10nMessages = Object.freeze({
3191     highlight: "pdfjs-editor-undo-bar-message-highlight",
3192     freetext: "pdfjs-editor-undo-bar-message-freetext",
3193     stamp: "pdfjs-editor-undo-bar-message-stamp",
3194     ink: "pdfjs-editor-undo-bar-message-ink",
3195     signature: "pdfjs-editor-undo-bar-message-signature",
3196     _multiple: "pdfjs-editor-undo-bar-message-multiple"
3197   });
3198   constructor({
3199     container,
3200     message,
3201     undoButton,
3202     closeButton
3203   }, eventBus) {
3204     this.#container = container;
3205     this.#message = message;
3206     this.#undoButton = undoButton;
3207     this.#closeButton = closeButton;
3208     this.#eventBus = eventBus;
3209   }
3210   destroy() {
3211     this.#initController?.abort();
3212     this.#initController = null;
3213     this.hide();
3214   }
3215   show(undoAction, messageData) {
3216     if (!this.#initController) {
3217       this.#initController = new AbortController();
3218       const opts = {
3219         signal: this.#initController.signal
3220       };
3221       const boundHide = this.hide.bind(this);
3222       this.#container.addEventListener("contextmenu", noContextMenu, opts);
3223       this.#closeButton.addEventListener("click", boundHide, opts);
3224       this.#eventBus._on("beforeprint", boundHide, opts);
3225       this.#eventBus._on("download", boundHide, opts);
3226     }
3227     this.hide();
3228     if (typeof messageData === "string") {
3229       this.#message.setAttribute("data-l10n-id", EditorUndoBar.#l10nMessages[messageData]);
3230     } else {
3231       this.#message.setAttribute("data-l10n-id", EditorUndoBar.#l10nMessages._multiple);
3232       this.#message.setAttribute("data-l10n-args", JSON.stringify({
3233         count: messageData
3234       }));
3235     }
3236     this.isOpen = true;
3237     this.#container.hidden = false;
3238     this.#showController = new AbortController();
3239     this.#undoButton.addEventListener("click", () => {
3240       undoAction();
3241       this.hide();
3242     }, {
3243       signal: this.#showController.signal
3244     });
3245     this.#focusTimeout = setTimeout(() => {
3246       this.#container.focus();
3247       this.#focusTimeout = null;
3248     }, 100);
3249   }
3250   hide() {
3251     if (!this.isOpen) {
3252       return;
3253     }
3254     this.isOpen = false;
3255     this.#container.hidden = true;
3256     this.#showController?.abort();
3257     this.#showController = null;
3258     if (this.#focusTimeout) {
3259       clearTimeout(this.#focusTimeout);
3260       this.#focusTimeout = null;
3261     }
3262   }
3265 ;// ./web/overlay_manager.js
3266 class OverlayManager {
3267   #overlays = new WeakMap();
3268   #active = null;
3269   get active() {
3270     return this.#active;
3271   }
3272   async register(dialog, canForceClose = false) {
3273     if (typeof dialog !== "object") {
3274       throw new Error("Not enough parameters.");
3275     } else if (this.#overlays.has(dialog)) {
3276       throw new Error("The overlay is already registered.");
3277     }
3278     this.#overlays.set(dialog, {
3279       canForceClose
3280     });
3281     dialog.addEventListener("cancel", ({
3282       target
3283     }) => {
3284       if (this.#active === target) {
3285         this.#active = null;
3286       }
3287     });
3288   }
3289   async open(dialog) {
3290     if (!this.#overlays.has(dialog)) {
3291       throw new Error("The overlay does not exist.");
3292     } else if (this.#active) {
3293       if (this.#active === dialog) {
3294         throw new Error("The overlay is already active.");
3295       } else if (this.#overlays.get(dialog).canForceClose) {
3296         await this.close();
3297       } else {
3298         throw new Error("Another overlay is currently active.");
3299       }
3300     }
3301     this.#active = dialog;
3302     dialog.showModal();
3303   }
3304   async close(dialog = this.#active) {
3305     if (!this.#overlays.has(dialog)) {
3306       throw new Error("The overlay does not exist.");
3307     } else if (!this.#active) {
3308       throw new Error("The overlay is currently not active.");
3309     } else if (this.#active !== dialog) {
3310       throw new Error("Another overlay is currently active.");
3311     }
3312     dialog.close();
3313     this.#active = null;
3314   }
3317 ;// ./web/password_prompt.js
3319 class PasswordPrompt {
3320   #activeCapability = null;
3321   #updateCallback = null;
3322   #reason = null;
3323   constructor(options, overlayManager, isViewerEmbedded = false) {
3324     this.dialog = options.dialog;
3325     this.label = options.label;
3326     this.input = options.input;
3327     this.submitButton = options.submitButton;
3328     this.cancelButton = options.cancelButton;
3329     this.overlayManager = overlayManager;
3330     this._isViewerEmbedded = isViewerEmbedded;
3331     this.submitButton.addEventListener("click", this.#verify.bind(this));
3332     this.cancelButton.addEventListener("click", this.close.bind(this));
3333     this.input.addEventListener("keydown", e => {
3334       if (e.keyCode === 13) {
3335         this.#verify();
3336       }
3337     });
3338     this.overlayManager.register(this.dialog, true);
3339     this.dialog.addEventListener("close", this.#cancel.bind(this));
3340   }
3341   async open() {
3342     await this.#activeCapability?.promise;
3343     this.#activeCapability = Promise.withResolvers();
3344     try {
3345       await this.overlayManager.open(this.dialog);
3346     } catch (ex) {
3347       this.#activeCapability.resolve();
3348       throw ex;
3349     }
3350     const passwordIncorrect = this.#reason === PasswordResponses.INCORRECT_PASSWORD;
3351     if (!this._isViewerEmbedded || passwordIncorrect) {
3352       this.input.focus();
3353     }
3354     this.label.setAttribute("data-l10n-id", passwordIncorrect ? "pdfjs-password-invalid" : "pdfjs-password-label");
3355   }
3356   async close() {
3357     if (this.overlayManager.active === this.dialog) {
3358       this.overlayManager.close(this.dialog);
3359     }
3360   }
3361   #verify() {
3362     const password = this.input.value;
3363     if (password?.length > 0) {
3364       this.#invokeCallback(password);
3365     }
3366   }
3367   #cancel() {
3368     this.#invokeCallback(new Error("PasswordPrompt cancelled."));
3369     this.#activeCapability.resolve();
3370   }
3371   #invokeCallback(password) {
3372     if (!this.#updateCallback) {
3373       return;
3374     }
3375     this.close();
3376     this.input.value = "";
3377     this.#updateCallback(password);
3378     this.#updateCallback = null;
3379   }
3380   async setUpdateCallback(updateCallback, reason) {
3381     if (this.#activeCapability) {
3382       await this.#activeCapability.promise;
3383     }
3384     this.#updateCallback = updateCallback;
3385     this.#reason = reason;
3386   }
3389 ;// ./web/base_tree_viewer.js
3391 const TREEITEM_OFFSET_TOP = -100;
3392 const TREEITEM_SELECTED_CLASS = "selected";
3393 class BaseTreeViewer {
3394   constructor(options) {
3395     this.container = options.container;
3396     this.eventBus = options.eventBus;
3397     this._l10n = options.l10n;
3398     this.reset();
3399   }
3400   reset() {
3401     this._pdfDocument = null;
3402     this._lastToggleIsShow = true;
3403     this._currentTreeItem = null;
3404     this.container.textContent = "";
3405     this.container.classList.remove("treeWithDeepNesting");
3406   }
3407   _dispatchEvent(count) {
3408     throw new Error("Not implemented: _dispatchEvent");
3409   }
3410   _bindLink(element, params) {
3411     throw new Error("Not implemented: _bindLink");
3412   }
3413   _normalizeTextContent(str) {
3414     return removeNullCharacters(str, true) || "\u2013";
3415   }
3416   _addToggleButton(div, hidden = false) {
3417     const toggler = document.createElement("div");
3418     toggler.className = "treeItemToggler";
3419     if (hidden) {
3420       toggler.classList.add("treeItemsHidden");
3421     }
3422     toggler.onclick = evt => {
3423       evt.stopPropagation();
3424       toggler.classList.toggle("treeItemsHidden");
3425       if (evt.shiftKey) {
3426         const shouldShowAll = !toggler.classList.contains("treeItemsHidden");
3427         this._toggleTreeItem(div, shouldShowAll);
3428       }
3429     };
3430     div.prepend(toggler);
3431   }
3432   _toggleTreeItem(root, show = false) {
3433     this._l10n.pause();
3434     this._lastToggleIsShow = show;
3435     for (const toggler of root.querySelectorAll(".treeItemToggler")) {
3436       toggler.classList.toggle("treeItemsHidden", !show);
3437     }
3438     this._l10n.resume();
3439   }
3440   _toggleAllTreeItems() {
3441     this._toggleTreeItem(this.container, !this._lastToggleIsShow);
3442   }
3443   _finishRendering(fragment, count, hasAnyNesting = false) {
3444     if (hasAnyNesting) {
3445       this.container.classList.add("treeWithDeepNesting");
3446       this._lastToggleIsShow = !fragment.querySelector(".treeItemsHidden");
3447     }
3448     this._l10n.pause();
3449     this.container.append(fragment);
3450     this._l10n.resume();
3451     this._dispatchEvent(count);
3452   }
3453   render(params) {
3454     throw new Error("Not implemented: render");
3455   }
3456   _updateCurrentTreeItem(treeItem = null) {
3457     if (this._currentTreeItem) {
3458       this._currentTreeItem.classList.remove(TREEITEM_SELECTED_CLASS);
3459       this._currentTreeItem = null;
3460     }
3461     if (treeItem) {
3462       treeItem.classList.add(TREEITEM_SELECTED_CLASS);
3463       this._currentTreeItem = treeItem;
3464     }
3465   }
3466   _scrollToCurrentTreeItem(treeItem) {
3467     if (!treeItem) {
3468       return;
3469     }
3470     this._l10n.pause();
3471     let currentNode = treeItem.parentNode;
3472     while (currentNode && currentNode !== this.container) {
3473       if (currentNode.classList.contains("treeItem")) {
3474         const toggler = currentNode.firstElementChild;
3475         toggler?.classList.remove("treeItemsHidden");
3476       }
3477       currentNode = currentNode.parentNode;
3478     }
3479     this._l10n.resume();
3480     this._updateCurrentTreeItem(treeItem);
3481     this.container.scrollTo(treeItem.offsetLeft, treeItem.offsetTop + TREEITEM_OFFSET_TOP);
3482   }
3485 ;// ./web/pdf_attachment_viewer.js
3488 class PDFAttachmentViewer extends BaseTreeViewer {
3489   constructor(options) {
3490     super(options);
3491     this.downloadManager = options.downloadManager;
3492     this.eventBus._on("fileattachmentannotation", this.#appendAttachment.bind(this));
3493   }
3494   reset(keepRenderedCapability = false) {
3495     super.reset();
3496     this._attachments = null;
3497     if (!keepRenderedCapability) {
3498       this._renderedCapability = Promise.withResolvers();
3499     }
3500     this._pendingDispatchEvent = false;
3501   }
3502   async _dispatchEvent(attachmentsCount) {
3503     this._renderedCapability.resolve();
3504     if (attachmentsCount === 0 && !this._pendingDispatchEvent) {
3505       this._pendingDispatchEvent = true;
3506       await waitOnEventOrTimeout({
3507         target: this.eventBus,
3508         name: "annotationlayerrendered",
3509         delay: 1000
3510       });
3511       if (!this._pendingDispatchEvent) {
3512         return;
3513       }
3514     }
3515     this._pendingDispatchEvent = false;
3516     this.eventBus.dispatch("attachmentsloaded", {
3517       source: this,
3518       attachmentsCount
3519     });
3520   }
3521   _bindLink(element, {
3522     content,
3523     description,
3524     filename
3525   }) {
3526     if (description) {
3527       element.title = description;
3528     }
3529     element.onclick = () => {
3530       this.downloadManager.openOrDownloadData(content, filename);
3531       return false;
3532     };
3533   }
3534   render({
3535     attachments,
3536     keepRenderedCapability = false
3537   }) {
3538     if (this._attachments) {
3539       this.reset(keepRenderedCapability);
3540     }
3541     this._attachments = attachments || null;
3542     if (!attachments) {
3543       this._dispatchEvent(0);
3544       return;
3545     }
3546     const fragment = document.createDocumentFragment();
3547     let attachmentsCount = 0;
3548     for (const name in attachments) {
3549       const item = attachments[name];
3550       const div = document.createElement("div");
3551       div.className = "treeItem";
3552       const element = document.createElement("a");
3553       this._bindLink(element, item);
3554       element.textContent = this._normalizeTextContent(item.filename);
3555       div.append(element);
3556       fragment.append(div);
3557       attachmentsCount++;
3558     }
3559     this._finishRendering(fragment, attachmentsCount);
3560   }
3561   #appendAttachment(item) {
3562     const renderedPromise = this._renderedCapability.promise;
3563     renderedPromise.then(() => {
3564       if (renderedPromise !== this._renderedCapability.promise) {
3565         return;
3566       }
3567       const attachments = this._attachments || Object.create(null);
3568       for (const name in attachments) {
3569         if (item.filename === name) {
3570           return;
3571         }
3572       }
3573       attachments[item.filename] = item;
3574       this.render({
3575         attachments,
3576         keepRenderedCapability: true
3577       });
3578     });
3579   }
3582 ;// ./web/grab_to_pan.js
3584 const CSS_CLASS_GRAB = "grab-to-pan-grab";
3585 class GrabToPan {
3586   #activateAC = null;
3587   #mouseDownAC = null;
3588   #scrollAC = null;
3589   constructor({
3590     element
3591   }) {
3592     this.element = element;
3593     this.document = element.ownerDocument;
3594     const overlay = this.overlay = document.createElement("div");
3595     overlay.className = "grab-to-pan-grabbing";
3596   }
3597   activate() {
3598     if (!this.#activateAC) {
3599       this.#activateAC = new AbortController();
3600       this.element.addEventListener("mousedown", this.#onMouseDown.bind(this), {
3601         capture: true,
3602         signal: this.#activateAC.signal
3603       });
3604       this.element.classList.add(CSS_CLASS_GRAB);
3605     }
3606   }
3607   deactivate() {
3608     if (this.#activateAC) {
3609       this.#activateAC.abort();
3610       this.#activateAC = null;
3611       this.#endPan();
3612       this.element.classList.remove(CSS_CLASS_GRAB);
3613     }
3614   }
3615   toggle() {
3616     if (this.#activateAC) {
3617       this.deactivate();
3618     } else {
3619       this.activate();
3620     }
3621   }
3622   ignoreTarget(node) {
3623     return node.matches("a[href], a[href] *, input, textarea, button, button *, select, option");
3624   }
3625   #onMouseDown(event) {
3626     if (event.button !== 0 || this.ignoreTarget(event.target)) {
3627       return;
3628     }
3629     if (event.originalTarget) {
3630       try {
3631         event.originalTarget.tagName;
3632       } catch {
3633         return;
3634       }
3635     }
3636     this.scrollLeftStart = this.element.scrollLeft;
3637     this.scrollTopStart = this.element.scrollTop;
3638     this.clientXStart = event.clientX;
3639     this.clientYStart = event.clientY;
3640     this.#mouseDownAC = new AbortController();
3641     const boundEndPan = this.#endPan.bind(this),
3642       mouseOpts = {
3643         capture: true,
3644         signal: this.#mouseDownAC.signal
3645       };
3646     this.document.addEventListener("mousemove", this.#onMouseMove.bind(this), mouseOpts);
3647     this.document.addEventListener("mouseup", boundEndPan, mouseOpts);
3648     this.#scrollAC = new AbortController();
3649     this.element.addEventListener("scroll", boundEndPan, {
3650       capture: true,
3651       signal: this.#scrollAC.signal
3652     });
3653     stopEvent(event);
3654     const focusedElement = document.activeElement;
3655     if (focusedElement && !focusedElement.contains(event.target)) {
3656       focusedElement.blur();
3657     }
3658   }
3659   #onMouseMove(event) {
3660     this.#scrollAC?.abort();
3661     this.#scrollAC = null;
3662     if (!(event.buttons & 1)) {
3663       this.#endPan();
3664       return;
3665     }
3666     const xDiff = event.clientX - this.clientXStart;
3667     const yDiff = event.clientY - this.clientYStart;
3668     this.element.scrollTo({
3669       top: this.scrollTopStart - yDiff,
3670       left: this.scrollLeftStart - xDiff,
3671       behavior: "instant"
3672     });
3673     if (!this.overlay.parentNode) {
3674       document.body.append(this.overlay);
3675     }
3676   }
3677   #endPan() {
3678     this.#mouseDownAC?.abort();
3679     this.#mouseDownAC = null;
3680     this.#scrollAC?.abort();
3681     this.#scrollAC = null;
3682     this.overlay.remove();
3683   }
3686 ;// ./web/pdf_cursor_tools.js
3690 class PDFCursorTools {
3691   #active = CursorTool.SELECT;
3692   #prevActive = null;
3693   constructor({
3694     container,
3695     eventBus,
3696     cursorToolOnLoad = CursorTool.SELECT
3697   }) {
3698     this.container = container;
3699     this.eventBus = eventBus;
3700     this.#addEventListeners();
3701     Promise.resolve().then(() => {
3702       this.switchTool(cursorToolOnLoad);
3703     });
3704   }
3705   get activeTool() {
3706     return this.#active;
3707   }
3708   switchTool(tool) {
3709     if (this.#prevActive !== null) {
3710       return;
3711     }
3712     this.#switchTool(tool);
3713   }
3714   #switchTool(tool, disabled = false) {
3715     if (tool === this.#active) {
3716       if (this.#prevActive !== null) {
3717         this.eventBus.dispatch("cursortoolchanged", {
3718           source: this,
3719           tool,
3720           disabled
3721         });
3722       }
3723       return;
3724     }
3725     const disableActiveTool = () => {
3726       switch (this.#active) {
3727         case CursorTool.SELECT:
3728           break;
3729         case CursorTool.HAND:
3730           this._handTool.deactivate();
3731           break;
3732         case CursorTool.ZOOM:
3733       }
3734     };
3735     switch (tool) {
3736       case CursorTool.SELECT:
3737         disableActiveTool();
3738         break;
3739       case CursorTool.HAND:
3740         disableActiveTool();
3741         this._handTool.activate();
3742         break;
3743       case CursorTool.ZOOM:
3744       default:
3745         console.error(`switchTool: "${tool}" is an unsupported value.`);
3746         return;
3747     }
3748     this.#active = tool;
3749     this.eventBus.dispatch("cursortoolchanged", {
3750       source: this,
3751       tool,
3752       disabled
3753     });
3754   }
3755   #addEventListeners() {
3756     this.eventBus._on("switchcursortool", evt => {
3757       if (!evt.reset) {
3758         this.switchTool(evt.tool);
3759       } else if (this.#prevActive !== null) {
3760         annotationEditorMode = AnnotationEditorType.NONE;
3761         presentationModeState = PresentationModeState.NORMAL;
3762         enableActive();
3763       }
3764     });
3765     let annotationEditorMode = AnnotationEditorType.NONE,
3766       presentationModeState = PresentationModeState.NORMAL;
3767     const disableActive = () => {
3768       this.#prevActive ??= this.#active;
3769       this.#switchTool(CursorTool.SELECT, true);
3770     };
3771     const enableActive = () => {
3772       if (this.#prevActive !== null && annotationEditorMode === AnnotationEditorType.NONE && presentationModeState === PresentationModeState.NORMAL) {
3773         this.#switchTool(this.#prevActive);
3774         this.#prevActive = null;
3775       }
3776     };
3777     this.eventBus._on("annotationeditormodechanged", ({
3778       mode
3779     }) => {
3780       annotationEditorMode = mode;
3781       if (mode === AnnotationEditorType.NONE) {
3782         enableActive();
3783       } else {
3784         disableActive();
3785       }
3786     });
3787     this.eventBus._on("presentationmodechanged", ({
3788       state
3789     }) => {
3790       presentationModeState = state;
3791       if (state === PresentationModeState.NORMAL) {
3792         enableActive();
3793       } else if (state === PresentationModeState.FULLSCREEN) {
3794         disableActive();
3795       }
3796     });
3797   }
3798   get _handTool() {
3799     return shadow(this, "_handTool", new GrabToPan({
3800       element: this.container
3801     }));
3802   }
3805 ;// ./web/pdf_document_properties.js
3808 const NON_METRIC_LOCALES = ["en-us", "en-lr", "my"];
3809 const US_PAGE_NAMES = {
3810   "8.5x11": "pdfjs-document-properties-page-size-name-letter",
3811   "8.5x14": "pdfjs-document-properties-page-size-name-legal"
3813 const METRIC_PAGE_NAMES = {
3814   "297x420": "pdfjs-document-properties-page-size-name-a-three",
3815   "210x297": "pdfjs-document-properties-page-size-name-a-four"
3817 function getPageName(size, isPortrait, pageNames) {
3818   const width = isPortrait ? size.width : size.height;
3819   const height = isPortrait ? size.height : size.width;
3820   return pageNames[`${width}x${height}`];
3822 class PDFDocumentProperties {
3823   #fieldData = null;
3824   constructor({
3825     dialog,
3826     fields,
3827     closeButton
3828   }, overlayManager, eventBus, l10n, fileNameLookup) {
3829     this.dialog = dialog;
3830     this.fields = fields;
3831     this.overlayManager = overlayManager;
3832     this.l10n = l10n;
3833     this._fileNameLookup = fileNameLookup;
3834     this.#reset();
3835     closeButton.addEventListener("click", this.close.bind(this));
3836     this.overlayManager.register(this.dialog);
3837     eventBus._on("pagechanging", evt => {
3838       this._currentPageNumber = evt.pageNumber;
3839     });
3840     eventBus._on("rotationchanging", evt => {
3841       this._pagesRotation = evt.pagesRotation;
3842     });
3843   }
3844   async open() {
3845     await Promise.all([this.overlayManager.open(this.dialog), this._dataAvailableCapability.promise]);
3846     const currentPageNumber = this._currentPageNumber;
3847     const pagesRotation = this._pagesRotation;
3848     if (this.#fieldData && currentPageNumber === this.#fieldData._currentPageNumber && pagesRotation === this.#fieldData._pagesRotation) {
3849       this.#updateUI();
3850       return;
3851     }
3852     const [{
3853       info,
3854       contentLength
3855     }, pdfPage] = await Promise.all([this.pdfDocument.getMetadata(), this.pdfDocument.getPage(currentPageNumber)]);
3856     const [fileName, fileSize, creationDate, modificationDate, pageSize, isLinearized] = await Promise.all([this._fileNameLookup(), this.#parseFileSize(contentLength), this.#parseDate(info.CreationDate), this.#parseDate(info.ModDate), this.#parsePageSize(getPageSizeInches(pdfPage), pagesRotation), this.#parseLinearization(info.IsLinearized)]);
3857     this.#fieldData = Object.freeze({
3858       fileName,
3859       fileSize,
3860       title: info.Title,
3861       author: info.Author,
3862       subject: info.Subject,
3863       keywords: info.Keywords,
3864       creationDate,
3865       modificationDate,
3866       creator: info.Creator,
3867       producer: info.Producer,
3868       version: info.PDFFormatVersion,
3869       pageCount: this.pdfDocument.numPages,
3870       pageSize,
3871       linearized: isLinearized,
3872       _currentPageNumber: currentPageNumber,
3873       _pagesRotation: pagesRotation
3874     });
3875     this.#updateUI();
3876     const {
3877       length
3878     } = await this.pdfDocument.getDownloadInfo();
3879     if (contentLength === length) {
3880       return;
3881     }
3882     const data = Object.assign(Object.create(null), this.#fieldData);
3883     data.fileSize = await this.#parseFileSize(length);
3884     this.#fieldData = Object.freeze(data);
3885     this.#updateUI();
3886   }
3887   async close() {
3888     this.overlayManager.close(this.dialog);
3889   }
3890   setDocument(pdfDocument) {
3891     if (this.pdfDocument) {
3892       this.#reset();
3893       this.#updateUI();
3894     }
3895     if (!pdfDocument) {
3896       return;
3897     }
3898     this.pdfDocument = pdfDocument;
3899     this._dataAvailableCapability.resolve();
3900   }
3901   #reset() {
3902     this.pdfDocument = null;
3903     this.#fieldData = null;
3904     this._dataAvailableCapability = Promise.withResolvers();
3905     this._currentPageNumber = 1;
3906     this._pagesRotation = 0;
3907   }
3908   #updateUI() {
3909     if (this.#fieldData && this.overlayManager.active !== this.dialog) {
3910       return;
3911     }
3912     for (const id in this.fields) {
3913       const content = this.#fieldData?.[id];
3914       this.fields[id].textContent = content || content === 0 ? content : "-";
3915     }
3916   }
3917   async #parseFileSize(b = 0) {
3918     const kb = b / 1024,
3919       mb = kb / 1024;
3920     return kb ? this.l10n.get(mb >= 1 ? "pdfjs-document-properties-size-mb" : "pdfjs-document-properties-size-kb", {
3921       mb,
3922       kb,
3923       b
3924     }) : undefined;
3925   }
3926   async #parsePageSize(pageSizeInches, pagesRotation) {
3927     if (!pageSizeInches) {
3928       return undefined;
3929     }
3930     if (pagesRotation % 180 !== 0) {
3931       pageSizeInches = {
3932         width: pageSizeInches.height,
3933         height: pageSizeInches.width
3934       };
3935     }
3936     const isPortrait = isPortraitOrientation(pageSizeInches),
3937       nonMetric = NON_METRIC_LOCALES.includes(this.l10n.getLanguage());
3938     let sizeInches = {
3939       width: Math.round(pageSizeInches.width * 100) / 100,
3940       height: Math.round(pageSizeInches.height * 100) / 100
3941     };
3942     let sizeMillimeters = {
3943       width: Math.round(pageSizeInches.width * 25.4 * 10) / 10,
3944       height: Math.round(pageSizeInches.height * 25.4 * 10) / 10
3945     };
3946     let nameId = getPageName(sizeInches, isPortrait, US_PAGE_NAMES) || getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES);
3947     if (!nameId && !(Number.isInteger(sizeMillimeters.width) && Number.isInteger(sizeMillimeters.height))) {
3948       const exactMillimeters = {
3949         width: pageSizeInches.width * 25.4,
3950         height: pageSizeInches.height * 25.4
3951       };
3952       const intMillimeters = {
3953         width: Math.round(sizeMillimeters.width),
3954         height: Math.round(sizeMillimeters.height)
3955       };
3956       if (Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 && Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1) {
3957         nameId = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES);
3958         if (nameId) {
3959           sizeInches = {
3960             width: Math.round(intMillimeters.width / 25.4 * 100) / 100,
3961             height: Math.round(intMillimeters.height / 25.4 * 100) / 100
3962           };
3963           sizeMillimeters = intMillimeters;
3964         }
3965       }
3966     }
3967     const [{
3968       width,
3969       height
3970     }, unit, name, orientation] = await Promise.all([nonMetric ? sizeInches : sizeMillimeters, this.l10n.get(nonMetric ? "pdfjs-document-properties-page-size-unit-inches" : "pdfjs-document-properties-page-size-unit-millimeters"), nameId && this.l10n.get(nameId), this.l10n.get(isPortrait ? "pdfjs-document-properties-page-size-orientation-portrait" : "pdfjs-document-properties-page-size-orientation-landscape")]);
3971     return this.l10n.get(name ? "pdfjs-document-properties-page-size-dimension-name-string" : "pdfjs-document-properties-page-size-dimension-string", {
3972       width,
3973       height,
3974       unit,
3975       name,
3976       orientation
3977     });
3978   }
3979   async #parseDate(inputDate) {
3980     const dateObj = PDFDateString.toDateObject(inputDate);
3981     return dateObj ? this.l10n.get("pdfjs-document-properties-date-time-string", {
3982       dateObj: dateObj.valueOf()
3983     }) : undefined;
3984   }
3985   #parseLinearization(isLinearized) {
3986     return this.l10n.get(isLinearized ? "pdfjs-document-properties-linearized-yes" : "pdfjs-document-properties-linearized-no");
3987   }
3990 ;// ./web/pdf_find_utils.js
3991 const CharacterType = {
3992   SPACE: 0,
3993   ALPHA_LETTER: 1,
3994   PUNCT: 2,
3995   HAN_LETTER: 3,
3996   KATAKANA_LETTER: 4,
3997   HIRAGANA_LETTER: 5,
3998   HALFWIDTH_KATAKANA_LETTER: 6,
3999   THAI_LETTER: 7
4001 function isAlphabeticalScript(charCode) {
4002   return charCode < 0x2e80;
4004 function isAscii(charCode) {
4005   return (charCode & 0xff80) === 0;
4007 function isAsciiAlpha(charCode) {
4008   return charCode >= 0x61 && charCode <= 0x7a || charCode >= 0x41 && charCode <= 0x5a;
4010 function isAsciiDigit(charCode) {
4011   return charCode >= 0x30 && charCode <= 0x39;
4013 function isAsciiSpace(charCode) {
4014   return charCode === 0x20 || charCode === 0x09 || charCode === 0x0d || charCode === 0x0a;
4016 function isHan(charCode) {
4017   return charCode >= 0x3400 && charCode <= 0x9fff || charCode >= 0xf900 && charCode <= 0xfaff;
4019 function isKatakana(charCode) {
4020   return charCode >= 0x30a0 && charCode <= 0x30ff;
4022 function isHiragana(charCode) {
4023   return charCode >= 0x3040 && charCode <= 0x309f;
4025 function isHalfwidthKatakana(charCode) {
4026   return charCode >= 0xff60 && charCode <= 0xff9f;
4028 function isThai(charCode) {
4029   return (charCode & 0xff80) === 0x0e00;
4031 function getCharacterType(charCode) {
4032   if (isAlphabeticalScript(charCode)) {
4033     if (isAscii(charCode)) {
4034       if (isAsciiSpace(charCode)) {
4035         return CharacterType.SPACE;
4036       } else if (isAsciiAlpha(charCode) || isAsciiDigit(charCode) || charCode === 0x5f) {
4037         return CharacterType.ALPHA_LETTER;
4038       }
4039       return CharacterType.PUNCT;
4040     } else if (isThai(charCode)) {
4041       return CharacterType.THAI_LETTER;
4042     } else if (charCode === 0xa0) {
4043       return CharacterType.SPACE;
4044     }
4045     return CharacterType.ALPHA_LETTER;
4046   }
4047   if (isHan(charCode)) {
4048     return CharacterType.HAN_LETTER;
4049   } else if (isKatakana(charCode)) {
4050     return CharacterType.KATAKANA_LETTER;
4051   } else if (isHiragana(charCode)) {
4052     return CharacterType.HIRAGANA_LETTER;
4053   } else if (isHalfwidthKatakana(charCode)) {
4054     return CharacterType.HALFWIDTH_KATAKANA_LETTER;
4055   }
4056   return CharacterType.ALPHA_LETTER;
4058 let NormalizeWithNFKC;
4059 function getNormalizeWithNFKC() {
4060   NormalizeWithNFKC ||= ` ¨ª¯²-µ¸-º¼-¾IJ-ijĿ-ŀʼnſDŽ-njDZ-dzʰ-ʸ˘-˝ˠ-ˤʹͺ;΄-΅·ϐ-ϖϰ-ϲϴ-ϵϹևٵ-ٸक़-य़ড়-ঢ়য়ਲ਼ਸ਼ਖ਼-ਜ਼ਫ਼ଡ଼-ଢ଼ำຳໜ-ໝ༌གྷཌྷདྷབྷཛྷཀྵჼᴬ-ᴮᴰ-ᴺᴼ-ᵍᵏ-ᵪᵸᶛ-ᶿẚ-ẛάέήίόύώΆ᾽-῁ΈΉ῍-῏ΐΊ῝-῟ΰΎ῭-`ΌΏ´-῾ - ‑‗․-… ″-‴‶-‷‼‾⁇-⁉⁗ ⁰-ⁱ⁴-₎ₐ-ₜ₨℀-℃℅-ℇ℉-ℓℕ-№ℙ-ℝ℠-™ℤΩℨK-ℭℯ-ℱℳ-ℹ℻-⅀ⅅ-ⅉ⅐-ⅿ↉∬-∭∯-∰〈-〉①-⓪⨌⩴-⩶⫝̸ⱼ-ⱽⵯ⺟⻳⼀-⿕ 〶〸-〺゛-゜ゟヿㄱ-ㆎ㆒-㆟㈀-㈞㈠-㉇㉐-㉾㊀-㏿ꚜ-ꚝꝰꟲ-ꟴꟸ-ꟹꭜ-ꭟꭩ豈-嗀塚晴凞-羽蘒諸逸-都飯-舘並-龎ff-stﬓ-ﬗיִײַ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-﷼︐-︙︰-﹄﹇-﹒﹔-﹦﹨-﹫ﹰ-ﹲﹴﹶ-ﻼ!-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ¢-₩`;
4061   return NormalizeWithNFKC;
4064 ;// ./web/pdf_find_controller.js
4067 const FindState = {
4068   FOUND: 0,
4069   NOT_FOUND: 1,
4070   WRAPPED: 2,
4071   PENDING: 3
4073 const FIND_TIMEOUT = 250;
4074 const MATCH_SCROLL_OFFSET_TOP = -50;
4075 const MATCH_SCROLL_OFFSET_LEFT = -400;
4076 const CHARACTERS_TO_NORMALIZE = {
4077   "\u2010": "-",
4078   "\u2018": "'",
4079   "\u2019": "'",
4080   "\u201A": "'",
4081   "\u201B": "'",
4082   "\u201C": '"',
4083   "\u201D": '"',
4084   "\u201E": '"',
4085   "\u201F": '"',
4086   "\u00BC": "1/4",
4087   "\u00BD": "1/2",
4088   "\u00BE": "3/4"
4090 const DIACRITICS_EXCEPTION = new Set([0x3099, 0x309a, 0x094d, 0x09cd, 0x0a4d, 0x0acd, 0x0b4d, 0x0bcd, 0x0c4d, 0x0ccd, 0x0d3b, 0x0d3c, 0x0d4d, 0x0dca, 0x0e3a, 0x0eba, 0x0f84, 0x1039, 0x103a, 0x1714, 0x1734, 0x17d2, 0x1a60, 0x1b44, 0x1baa, 0x1bab, 0x1bf2, 0x1bf3, 0x2d7f, 0xa806, 0xa82c, 0xa8c4, 0xa953, 0xa9c0, 0xaaf6, 0xabed, 0x0c56, 0x0f71, 0x0f72, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f80, 0x0f74]);
4091 let DIACRITICS_EXCEPTION_STR;
4092 const DIACRITICS_REG_EXP = /\p{M}+/gu;
4093 const SPECIAL_CHARS_REG_EXP = /([.*+?^${}()|[\]\\])|(\p{P})|(\s+)|(\p{M})|(\p{L})/gu;
4094 const NOT_DIACRITIC_FROM_END_REG_EXP = /([^\p{M}])\p{M}*$/u;
4095 const NOT_DIACRITIC_FROM_START_REG_EXP = /^\p{M}*([^\p{M}])/u;
4096 const SYLLABLES_REG_EXP = /[\uAC00-\uD7AF\uFA6C\uFACF-\uFAD1\uFAD5-\uFAD7]+/g;
4097 const SYLLABLES_LENGTHS = new Map();
4098 const FIRST_CHAR_SYLLABLES_REG_EXP = "[\\u1100-\\u1112\\ud7a4-\\ud7af\\ud84a\\ud84c\\ud850\\ud854\\ud857\\ud85f]";
4099 const NFKC_CHARS_TO_NORMALIZE = new Map();
4100 let noSyllablesRegExp = null;
4101 let withSyllablesRegExp = null;
4102 function normalize(text) {
4103   const syllablePositions = [];
4104   let m;
4105   while ((m = SYLLABLES_REG_EXP.exec(text)) !== null) {
4106     let {
4107       index
4108     } = m;
4109     for (const char of m[0]) {
4110       let len = SYLLABLES_LENGTHS.get(char);
4111       if (!len) {
4112         len = char.normalize("NFD").length;
4113         SYLLABLES_LENGTHS.set(char, len);
4114       }
4115       syllablePositions.push([len, index++]);
4116     }
4117   }
4118   const hasSyllables = syllablePositions.length > 0;
4119   let normalizationRegex;
4120   if (!hasSyllables && noSyllablesRegExp) {
4121     normalizationRegex = noSyllablesRegExp;
4122   } else if (hasSyllables && withSyllablesRegExp) {
4123     normalizationRegex = withSyllablesRegExp;
4124   } else {
4125     const replace = Object.keys(CHARACTERS_TO_NORMALIZE).join("");
4126     const toNormalizeWithNFKC = getNormalizeWithNFKC();
4127     const CJK = "(?:\\p{Ideographic}|[\u3040-\u30FF])";
4128     const HKDiacritics = "(?:\u3099|\u309A)";
4129     const BrokenWord = `\\p{Ll}-\\n(?=\\p{Ll})|\\p{Lu}-\\n(?=\\p{L})`;
4130     const regexps = [`[${replace}]`, `[${toNormalizeWithNFKC}]`, `${HKDiacritics}\\n`, "\\p{M}+(?:-\\n)?", `${BrokenWord}`, "\\S-\\n", `${CJK}\\n`, "\\n", hasSyllables ? FIRST_CHAR_SYLLABLES_REG_EXP : "\\u0000"];
4131     normalizationRegex = new RegExp(regexps.map(r => `(${r})`).join("|"), "gum");
4132     if (hasSyllables) {
4133       withSyllablesRegExp = normalizationRegex;
4134     } else {
4135       noSyllablesRegExp = normalizationRegex;
4136     }
4137   }
4138   const rawDiacriticsPositions = [];
4139   while ((m = DIACRITICS_REG_EXP.exec(text)) !== null) {
4140     rawDiacriticsPositions.push([m[0].length, m.index]);
4141   }
4142   let normalized = text.normalize("NFD");
4143   const positions = [0, 0];
4144   let rawDiacriticsIndex = 0;
4145   let syllableIndex = 0;
4146   let shift = 0;
4147   let shiftOrigin = 0;
4148   let eol = 0;
4149   let hasDiacritics = false;
4150   normalized = normalized.replace(normalizationRegex, (match, p1, p2, p3, p4, p5, p6, p7, p8, p9, i) => {
4151     i -= shiftOrigin;
4152     if (p1) {
4153       const replacement = CHARACTERS_TO_NORMALIZE[p1];
4154       const jj = replacement.length;
4155       for (let j = 1; j < jj; j++) {
4156         positions.push(i - shift + j, shift - j);
4157       }
4158       shift -= jj - 1;
4159       return replacement;
4160     }
4161     if (p2) {
4162       let replacement = NFKC_CHARS_TO_NORMALIZE.get(p2);
4163       if (!replacement) {
4164         replacement = p2.normalize("NFKC");
4165         NFKC_CHARS_TO_NORMALIZE.set(p2, replacement);
4166       }
4167       const jj = replacement.length;
4168       for (let j = 1; j < jj; j++) {
4169         positions.push(i - shift + j, shift - j);
4170       }
4171       shift -= jj - 1;
4172       return replacement;
4173     }
4174     if (p3) {
4175       hasDiacritics = true;
4176       if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {
4177         ++rawDiacriticsIndex;
4178       } else {
4179         positions.push(i - 1 - shift + 1, shift - 1);
4180         shift -= 1;
4181         shiftOrigin += 1;
4182       }
4183       positions.push(i - shift + 1, shift);
4184       shiftOrigin += 1;
4185       eol += 1;
4186       return p3.charAt(0);
4187     }
4188     if (p4) {
4189       const hasTrailingDashEOL = p4.endsWith("\n");
4190       const len = hasTrailingDashEOL ? p4.length - 2 : p4.length;
4191       hasDiacritics = true;
4192       let jj = len;
4193       if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {
4194         jj -= rawDiacriticsPositions[rawDiacriticsIndex][0];
4195         ++rawDiacriticsIndex;
4196       }
4197       for (let j = 1; j <= jj; j++) {
4198         positions.push(i - 1 - shift + j, shift - j);
4199       }
4200       shift -= jj;
4201       shiftOrigin += jj;
4202       if (hasTrailingDashEOL) {
4203         i += len - 1;
4204         positions.push(i - shift + 1, 1 + shift);
4205         shift += 1;
4206         shiftOrigin += 1;
4207         eol += 1;
4208         return p4.slice(0, len);
4209       }
4210       return p4;
4211     }
4212     if (p5) {
4213       const len = p5.length - 2;
4214       positions.push(i - shift + len, 1 + shift);
4215       shift += 1;
4216       shiftOrigin += 1;
4217       eol += 1;
4218       return p5.slice(0, -2);
4219     }
4220     if (p6) {
4221       shiftOrigin += 1;
4222       eol += 1;
4223       return p6.slice(0, -1);
4224     }
4225     if (p7) {
4226       const len = p7.length - 1;
4227       positions.push(i - shift + len, shift);
4228       shiftOrigin += 1;
4229       eol += 1;
4230       return p7.slice(0, -1);
4231     }
4232     if (p8) {
4233       positions.push(i - shift + 1, shift - 1);
4234       shift -= 1;
4235       shiftOrigin += 1;
4236       eol += 1;
4237       return " ";
4238     }
4239     if (i + eol === syllablePositions[syllableIndex]?.[1]) {
4240       const newCharLen = syllablePositions[syllableIndex][0] - 1;
4241       ++syllableIndex;
4242       for (let j = 1; j <= newCharLen; j++) {
4243         positions.push(i - (shift - j), shift - j);
4244       }
4245       shift -= newCharLen;
4246       shiftOrigin += newCharLen;
4247     }
4248     return p9;
4249   });
4250   positions.push(normalized.length, shift);
4251   const starts = new Uint32Array(positions.length >> 1);
4252   const shifts = new Int32Array(positions.length >> 1);
4253   for (let i = 0, ii = positions.length; i < ii; i += 2) {
4254     starts[i >> 1] = positions[i];
4255     shifts[i >> 1] = positions[i + 1];
4256   }
4257   return [normalized, [starts, shifts], hasDiacritics];
4259 function getOriginalIndex(diffs, pos, len) {
4260   if (!diffs) {
4261     return [pos, len];
4262   }
4263   const [starts, shifts] = diffs;
4264   const start = pos;
4265   const end = pos + len - 1;
4266   let i = binarySearchFirstItem(starts, x => x >= start);
4267   if (starts[i] > start) {
4268     --i;
4269   }
4270   let j = binarySearchFirstItem(starts, x => x >= end, i);
4271   if (starts[j] > end) {
4272     --j;
4273   }
4274   const oldStart = start + shifts[i];
4275   const oldEnd = end + shifts[j];
4276   const oldLen = oldEnd + 1 - oldStart;
4277   return [oldStart, oldLen];
4279 class PDFFindController {
4280   #state = null;
4281   #updateMatchesCountOnProgress = true;
4282   #visitedPagesCount = 0;
4283   constructor({
4284     linkService,
4285     eventBus,
4286     updateMatchesCountOnProgress = true
4287   }) {
4288     this._linkService = linkService;
4289     this._eventBus = eventBus;
4290     this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress;
4291     this.onIsPageVisible = null;
4292     this.#reset();
4293     eventBus._on("find", this.#onFind.bind(this));
4294     eventBus._on("findbarclose", this.#onFindBarClose.bind(this));
4295   }
4296   get highlightMatches() {
4297     return this._highlightMatches;
4298   }
4299   get pageMatches() {
4300     return this._pageMatches;
4301   }
4302   get pageMatchesLength() {
4303     return this._pageMatchesLength;
4304   }
4305   get selected() {
4306     return this._selected;
4307   }
4308   get state() {
4309     return this.#state;
4310   }
4311   setDocument(pdfDocument) {
4312     if (this._pdfDocument) {
4313       this.#reset();
4314     }
4315     if (!pdfDocument) {
4316       return;
4317     }
4318     this._pdfDocument = pdfDocument;
4319     this._firstPageCapability.resolve();
4320   }
4321   #onFind(state) {
4322     if (!state) {
4323       return;
4324     }
4325     const pdfDocument = this._pdfDocument;
4326     const {
4327       type
4328     } = state;
4329     if (this.#state === null || this.#shouldDirtyMatch(state)) {
4330       this._dirtyMatch = true;
4331     }
4332     this.#state = state;
4333     if (type !== "highlightallchange") {
4334       this.#updateUIState(FindState.PENDING);
4335     }
4336     this._firstPageCapability.promise.then(() => {
4337       if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {
4338         return;
4339       }
4340       this.#extractText();
4341       const findbarClosed = !this._highlightMatches;
4342       const pendingTimeout = !!this._findTimeout;
4343       if (this._findTimeout) {
4344         clearTimeout(this._findTimeout);
4345         this._findTimeout = null;
4346       }
4347       if (!type) {
4348         this._findTimeout = setTimeout(() => {
4349           this.#nextMatch();
4350           this._findTimeout = null;
4351         }, FIND_TIMEOUT);
4352       } else if (this._dirtyMatch) {
4353         this.#nextMatch();
4354       } else if (type === "again") {
4355         this.#nextMatch();
4356         if (findbarClosed && this.#state.highlightAll) {
4357           this.#updateAllPages();
4358         }
4359       } else if (type === "highlightallchange") {
4360         if (pendingTimeout) {
4361           this.#nextMatch();
4362         } else {
4363           this._highlightMatches = true;
4364         }
4365         this.#updateAllPages();
4366       } else {
4367         this.#nextMatch();
4368       }
4369     });
4370   }
4371   scrollMatchIntoView({
4372     element = null,
4373     selectedLeft = 0,
4374     pageIndex = -1,
4375     matchIndex = -1
4376   }) {
4377     if (!this._scrollMatches || !element) {
4378       return;
4379     } else if (matchIndex === -1 || matchIndex !== this._selected.matchIdx) {
4380       return;
4381     } else if (pageIndex === -1 || pageIndex !== this._selected.pageIdx) {
4382       return;
4383     }
4384     this._scrollMatches = false;
4385     const spot = {
4386       top: MATCH_SCROLL_OFFSET_TOP,
4387       left: selectedLeft + MATCH_SCROLL_OFFSET_LEFT
4388     };
4389     scrollIntoView(element, spot, true);
4390   }
4391   #reset() {
4392     this._highlightMatches = false;
4393     this._scrollMatches = false;
4394     this._pdfDocument = null;
4395     this._pageMatches = [];
4396     this._pageMatchesLength = [];
4397     this.#visitedPagesCount = 0;
4398     this.#state = null;
4399     this._selected = {
4400       pageIdx: -1,
4401       matchIdx: -1
4402     };
4403     this._offset = {
4404       pageIdx: null,
4405       matchIdx: null,
4406       wrapped: false
4407     };
4408     this._extractTextPromises = [];
4409     this._pageContents = [];
4410     this._pageDiffs = [];
4411     this._hasDiacritics = [];
4412     this._matchesCountTotal = 0;
4413     this._pagesToSearch = null;
4414     this._pendingFindMatches = new Set();
4415     this._resumePageIdx = null;
4416     this._dirtyMatch = false;
4417     clearTimeout(this._findTimeout);
4418     this._findTimeout = null;
4419     this._firstPageCapability = Promise.withResolvers();
4420   }
4421   get #query() {
4422     const {
4423       query
4424     } = this.#state;
4425     if (typeof query === "string") {
4426       if (query !== this._rawQuery) {
4427         this._rawQuery = query;
4428         [this._normalizedQuery] = normalize(query);
4429       }
4430       return this._normalizedQuery;
4431     }
4432     return (query || []).filter(q => !!q).map(q => normalize(q)[0]);
4433   }
4434   #shouldDirtyMatch(state) {
4435     const newQuery = state.query,
4436       prevQuery = this.#state.query;
4437     const newType = typeof newQuery,
4438       prevType = typeof prevQuery;
4439     if (newType !== prevType) {
4440       return true;
4441     }
4442     if (newType === "string") {
4443       if (newQuery !== prevQuery) {
4444         return true;
4445       }
4446     } else if (JSON.stringify(newQuery) !== JSON.stringify(prevQuery)) {
4447       return true;
4448     }
4449     switch (state.type) {
4450       case "again":
4451         const pageNumber = this._selected.pageIdx + 1;
4452         const linkService = this._linkService;
4453         return pageNumber >= 1 && pageNumber <= linkService.pagesCount && pageNumber !== linkService.page && !(this.onIsPageVisible?.(pageNumber) ?? true);
4454       case "highlightallchange":
4455         return false;
4456     }
4457     return true;
4458   }
4459   #isEntireWord(content, startIdx, length) {
4460     let match = content.slice(0, startIdx).match(NOT_DIACRITIC_FROM_END_REG_EXP);
4461     if (match) {
4462       const first = content.charCodeAt(startIdx);
4463       const limit = match[1].charCodeAt(0);
4464       if (getCharacterType(first) === getCharacterType(limit)) {
4465         return false;
4466       }
4467     }
4468     match = content.slice(startIdx + length).match(NOT_DIACRITIC_FROM_START_REG_EXP);
4469     if (match) {
4470       const last = content.charCodeAt(startIdx + length - 1);
4471       const limit = match[1].charCodeAt(0);
4472       if (getCharacterType(last) === getCharacterType(limit)) {
4473         return false;
4474       }
4475     }
4476     return true;
4477   }
4478   #convertToRegExpString(query, hasDiacritics) {
4479     const {
4480       matchDiacritics
4481     } = this.#state;
4482     let isUnicode = false;
4483     query = query.replaceAll(SPECIAL_CHARS_REG_EXP, (match, p1, p2, p3, p4, p5) => {
4484       if (p1) {
4485         return `[ ]*\\${p1}[ ]*`;
4486       }
4487       if (p2) {
4488         return `[ ]*${p2}[ ]*`;
4489       }
4490       if (p3) {
4491         return "[ ]+";
4492       }
4493       if (matchDiacritics) {
4494         return p4 || p5;
4495       }
4496       if (p4) {
4497         return DIACRITICS_EXCEPTION.has(p4.charCodeAt(0)) ? p4 : "";
4498       }
4499       if (hasDiacritics) {
4500         isUnicode = true;
4501         return `${p5}\\p{M}*`;
4502       }
4503       return p5;
4504     });
4505     const trailingSpaces = "[ ]*";
4506     if (query.endsWith(trailingSpaces)) {
4507       query = query.slice(0, query.length - trailingSpaces.length);
4508     }
4509     if (matchDiacritics) {
4510       if (hasDiacritics) {
4511         DIACRITICS_EXCEPTION_STR ||= String.fromCharCode(...DIACRITICS_EXCEPTION);
4512         isUnicode = true;
4513         query = `${query}(?=[${DIACRITICS_EXCEPTION_STR}]|[^\\p{M}]|$)`;
4514       }
4515     }
4516     return [isUnicode, query];
4517   }
4518   #calculateMatch(pageIndex) {
4519     const query = this.#query;
4520     if (query.length === 0) {
4521       return;
4522     }
4523     const pageContent = this._pageContents[pageIndex];
4524     const matcherResult = this.match(query, pageContent, pageIndex);
4525     const matches = this._pageMatches[pageIndex] = [];
4526     const matchesLength = this._pageMatchesLength[pageIndex] = [];
4527     const diffs = this._pageDiffs[pageIndex];
4528     matcherResult?.forEach(({
4529       index,
4530       length
4531     }) => {
4532       const [matchPos, matchLen] = getOriginalIndex(diffs, index, length);
4533       if (matchLen) {
4534         matches.push(matchPos);
4535         matchesLength.push(matchLen);
4536       }
4537     });
4538     if (this.#state.highlightAll) {
4539       this.#updatePage(pageIndex);
4540     }
4541     if (this._resumePageIdx === pageIndex) {
4542       this._resumePageIdx = null;
4543       this.#nextPageMatch();
4544     }
4545     const pageMatchesCount = matches.length;
4546     this._matchesCountTotal += pageMatchesCount;
4547     if (this.#updateMatchesCountOnProgress) {
4548       if (pageMatchesCount > 0) {
4549         this.#updateUIResultsCount();
4550       }
4551     } else if (++this.#visitedPagesCount === this._linkService.pagesCount) {
4552       this.#updateUIResultsCount();
4553     }
4554   }
4555   match(query, pageContent, pageIndex) {
4556     const hasDiacritics = this._hasDiacritics[pageIndex];
4557     let isUnicode = false;
4558     if (typeof query === "string") {
4559       [isUnicode, query] = this.#convertToRegExpString(query, hasDiacritics);
4560     } else {
4561       query = query.sort().reverse().map(q => {
4562         const [isUnicodePart, queryPart] = this.#convertToRegExpString(q, hasDiacritics);
4563         isUnicode ||= isUnicodePart;
4564         return `(${queryPart})`;
4565       }).join("|");
4566     }
4567     if (!query) {
4568       return undefined;
4569     }
4570     const {
4571       caseSensitive,
4572       entireWord
4573     } = this.#state;
4574     const flags = `g${isUnicode ? "u" : ""}${caseSensitive ? "" : "i"}`;
4575     query = new RegExp(query, flags);
4576     const matches = [];
4577     let match;
4578     while ((match = query.exec(pageContent)) !== null) {
4579       if (entireWord && !this.#isEntireWord(pageContent, match.index, match[0].length)) {
4580         continue;
4581       }
4582       matches.push({
4583         index: match.index,
4584         length: match[0].length
4585       });
4586     }
4587     return matches;
4588   }
4589   #extractText() {
4590     if (this._extractTextPromises.length > 0) {
4591       return;
4592     }
4593     let deferred = Promise.resolve();
4594     const textOptions = {
4595       disableNormalization: true
4596     };
4597     for (let i = 0, ii = this._linkService.pagesCount; i < ii; i++) {
4598       const {
4599         promise,
4600         resolve
4601       } = Promise.withResolvers();
4602       this._extractTextPromises[i] = promise;
4603       deferred = deferred.then(() => {
4604         return this._pdfDocument.getPage(i + 1).then(pdfPage => pdfPage.getTextContent(textOptions)).then(textContent => {
4605           const strBuf = [];
4606           for (const textItem of textContent.items) {
4607             strBuf.push(textItem.str);
4608             if (textItem.hasEOL) {
4609               strBuf.push("\n");
4610             }
4611           }
4612           [this._pageContents[i], this._pageDiffs[i], this._hasDiacritics[i]] = normalize(strBuf.join(""));
4613           resolve();
4614         }, reason => {
4615           console.error(`Unable to get text content for page ${i + 1}`, reason);
4616           this._pageContents[i] = "";
4617           this._pageDiffs[i] = null;
4618           this._hasDiacritics[i] = false;
4619           resolve();
4620         });
4621       });
4622     }
4623   }
4624   #updatePage(index) {
4625     if (this._scrollMatches && this._selected.pageIdx === index) {
4626       this._linkService.page = index + 1;
4627     }
4628     this._eventBus.dispatch("updatetextlayermatches", {
4629       source: this,
4630       pageIndex: index
4631     });
4632   }
4633   #updateAllPages() {
4634     this._eventBus.dispatch("updatetextlayermatches", {
4635       source: this,
4636       pageIndex: -1
4637     });
4638   }
4639   #nextMatch() {
4640     const previous = this.#state.findPrevious;
4641     const currentPageIndex = this._linkService.page - 1;
4642     const numPages = this._linkService.pagesCount;
4643     this._highlightMatches = true;
4644     if (this._dirtyMatch) {
4645       this._dirtyMatch = false;
4646       this._selected.pageIdx = this._selected.matchIdx = -1;
4647       this._offset.pageIdx = currentPageIndex;
4648       this._offset.matchIdx = null;
4649       this._offset.wrapped = false;
4650       this._resumePageIdx = null;
4651       this._pageMatches.length = 0;
4652       this._pageMatchesLength.length = 0;
4653       this.#visitedPagesCount = 0;
4654       this._matchesCountTotal = 0;
4655       this.#updateAllPages();
4656       for (let i = 0; i < numPages; i++) {
4657         if (this._pendingFindMatches.has(i)) {
4658           continue;
4659         }
4660         this._pendingFindMatches.add(i);
4661         this._extractTextPromises[i].then(() => {
4662           this._pendingFindMatches.delete(i);
4663           this.#calculateMatch(i);
4664         });
4665       }
4666     }
4667     const query = this.#query;
4668     if (query.length === 0) {
4669       this.#updateUIState(FindState.FOUND);
4670       return;
4671     }
4672     if (this._resumePageIdx) {
4673       return;
4674     }
4675     const offset = this._offset;
4676     this._pagesToSearch = numPages;
4677     if (offset.matchIdx !== null) {
4678       const numPageMatches = this._pageMatches[offset.pageIdx].length;
4679       if (!previous && offset.matchIdx + 1 < numPageMatches || previous && offset.matchIdx > 0) {
4680         offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
4681         this.#updateMatch(true);
4682         return;
4683       }
4684       this.#advanceOffsetPage(previous);
4685     }
4686     this.#nextPageMatch();
4687   }
4688   #matchesReady(matches) {
4689     const offset = this._offset;
4690     const numMatches = matches.length;
4691     const previous = this.#state.findPrevious;
4692     if (numMatches) {
4693       offset.matchIdx = previous ? numMatches - 1 : 0;
4694       this.#updateMatch(true);
4695       return true;
4696     }
4697     this.#advanceOffsetPage(previous);
4698     if (offset.wrapped) {
4699       offset.matchIdx = null;
4700       if (this._pagesToSearch < 0) {
4701         this.#updateMatch(false);
4702         return true;
4703       }
4704     }
4705     return false;
4706   }
4707   #nextPageMatch() {
4708     if (this._resumePageIdx !== null) {
4709       console.error("There can only be one pending page.");
4710     }
4711     let matches = null;
4712     do {
4713       const pageIdx = this._offset.pageIdx;
4714       matches = this._pageMatches[pageIdx];
4715       if (!matches) {
4716         this._resumePageIdx = pageIdx;
4717         break;
4718       }
4719     } while (!this.#matchesReady(matches));
4720   }
4721   #advanceOffsetPage(previous) {
4722     const offset = this._offset;
4723     const numPages = this._linkService.pagesCount;
4724     offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;
4725     offset.matchIdx = null;
4726     this._pagesToSearch--;
4727     if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
4728       offset.pageIdx = previous ? numPages - 1 : 0;
4729       offset.wrapped = true;
4730     }
4731   }
4732   #updateMatch(found = false) {
4733     let state = FindState.NOT_FOUND;
4734     const wrapped = this._offset.wrapped;
4735     this._offset.wrapped = false;
4736     if (found) {
4737       const previousPage = this._selected.pageIdx;
4738       this._selected.pageIdx = this._offset.pageIdx;
4739       this._selected.matchIdx = this._offset.matchIdx;
4740       state = wrapped ? FindState.WRAPPED : FindState.FOUND;
4741       if (previousPage !== -1 && previousPage !== this._selected.pageIdx) {
4742         this.#updatePage(previousPage);
4743       }
4744     }
4745     this.#updateUIState(state, this.#state.findPrevious);
4746     if (this._selected.pageIdx !== -1) {
4747       this._scrollMatches = true;
4748       this.#updatePage(this._selected.pageIdx);
4749     }
4750   }
4751   #onFindBarClose(evt) {
4752     const pdfDocument = this._pdfDocument;
4753     this._firstPageCapability.promise.then(() => {
4754       if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {
4755         return;
4756       }
4757       if (this._findTimeout) {
4758         clearTimeout(this._findTimeout);
4759         this._findTimeout = null;
4760       }
4761       if (this._resumePageIdx) {
4762         this._resumePageIdx = null;
4763         this._dirtyMatch = true;
4764       }
4765       this.#updateUIState(FindState.FOUND);
4766       this._highlightMatches = false;
4767       this.#updateAllPages();
4768     });
4769   }
4770   #requestMatchesCount() {
4771     const {
4772       pageIdx,
4773       matchIdx
4774     } = this._selected;
4775     let current = 0,
4776       total = this._matchesCountTotal;
4777     if (matchIdx !== -1) {
4778       for (let i = 0; i < pageIdx; i++) {
4779         current += this._pageMatches[i]?.length || 0;
4780       }
4781       current += matchIdx + 1;
4782     }
4783     if (current < 1 || current > total) {
4784       current = total = 0;
4785     }
4786     return {
4787       current,
4788       total
4789     };
4790   }
4791   #updateUIResultsCount() {
4792     this._eventBus.dispatch("updatefindmatchescount", {
4793       source: this,
4794       matchesCount: this.#requestMatchesCount()
4795     });
4796   }
4797   #updateUIState(state, previous = false) {
4798     if (!this.#updateMatchesCountOnProgress && (this.#visitedPagesCount !== this._linkService.pagesCount || state === FindState.PENDING)) {
4799       return;
4800     }
4801     this._eventBus.dispatch("updatefindcontrolstate", {
4802       source: this,
4803       state,
4804       previous,
4805       entireWord: this.#state?.entireWord ?? null,
4806       matchesCount: this.#requestMatchesCount(),
4807       rawQuery: this.#state?.query ?? null
4808     });
4809   }
4812 ;// ./web/pdf_find_bar.js
4815 const MATCHES_COUNT_LIMIT = 1000;
4816 class PDFFindBar {
4817   #mainContainer;
4818   #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
4819   constructor(options, mainContainer, eventBus) {
4820     this.opened = false;
4821     this.bar = options.bar;
4822     this.toggleButton = options.toggleButton;
4823     this.findField = options.findField;
4824     this.highlightAll = options.highlightAllCheckbox;
4825     this.caseSensitive = options.caseSensitiveCheckbox;
4826     this.matchDiacritics = options.matchDiacriticsCheckbox;
4827     this.entireWord = options.entireWordCheckbox;
4828     this.findMsg = options.findMsg;
4829     this.findResultsCount = options.findResultsCount;
4830     this.findPreviousButton = options.findPreviousButton;
4831     this.findNextButton = options.findNextButton;
4832     this.eventBus = eventBus;
4833     this.#mainContainer = mainContainer;
4834     const checkedInputs = new Map([[this.highlightAll, "highlightallchange"], [this.caseSensitive, "casesensitivitychange"], [this.entireWord, "entirewordchange"], [this.matchDiacritics, "diacriticmatchingchange"]]);
4835     this.toggleButton.addEventListener("click", () => {
4836       this.toggle();
4837     });
4838     this.findField.addEventListener("input", () => {
4839       this.dispatchEvent("");
4840     });
4841     this.bar.addEventListener("keydown", ({
4842       keyCode,
4843       shiftKey,
4844       target
4845     }) => {
4846       switch (keyCode) {
4847         case 13:
4848           if (target === this.findField) {
4849             this.dispatchEvent("again", shiftKey);
4850           } else if (checkedInputs.has(target)) {
4851             target.checked = !target.checked;
4852             this.dispatchEvent(checkedInputs.get(target));
4853           }
4854           break;
4855         case 27:
4856           this.close();
4857           break;
4858       }
4859     });
4860     this.findPreviousButton.addEventListener("click", () => {
4861       this.dispatchEvent("again", true);
4862     });
4863     this.findNextButton.addEventListener("click", () => {
4864       this.dispatchEvent("again", false);
4865     });
4866     for (const [elem, evtName] of checkedInputs) {
4867       elem.addEventListener("click", () => {
4868         this.dispatchEvent(evtName);
4869       });
4870     }
4871   }
4872   reset() {
4873     this.updateUIState();
4874   }
4875   dispatchEvent(type, findPrev = false) {
4876     this.eventBus.dispatch("find", {
4877       source: this,
4878       type,
4879       query: this.findField.value,
4880       caseSensitive: this.caseSensitive.checked,
4881       entireWord: this.entireWord.checked,
4882       highlightAll: this.highlightAll.checked,
4883       findPrevious: findPrev,
4884       matchDiacritics: this.matchDiacritics.checked
4885     });
4886   }
4887   updateUIState(state, previous, matchesCount) {
4888     const {
4889       findField,
4890       findMsg
4891     } = this;
4892     let findMsgId = "",
4893       status = "";
4894     switch (state) {
4895       case FindState.FOUND:
4896         break;
4897       case FindState.PENDING:
4898         status = "pending";
4899         break;
4900       case FindState.NOT_FOUND:
4901         findMsgId = "pdfjs-find-not-found";
4902         status = "notFound";
4903         break;
4904       case FindState.WRAPPED:
4905         findMsgId = previous ? "pdfjs-find-reached-top" : "pdfjs-find-reached-bottom";
4906         break;
4907     }
4908     findField.setAttribute("data-status", status);
4909     findField.setAttribute("aria-invalid", state === FindState.NOT_FOUND);
4910     findMsg.setAttribute("data-status", status);
4911     if (findMsgId) {
4912       findMsg.setAttribute("data-l10n-id", findMsgId);
4913     } else {
4914       findMsg.removeAttribute("data-l10n-id");
4915       findMsg.textContent = "";
4916     }
4917     this.updateResultsCount(matchesCount);
4918   }
4919   updateResultsCount({
4920     current = 0,
4921     total = 0
4922   } = {}) {
4923     const {
4924       findResultsCount
4925     } = this;
4926     if (total > 0) {
4927       const limit = MATCHES_COUNT_LIMIT;
4928       findResultsCount.setAttribute("data-l10n-id", total > limit ? "pdfjs-find-match-count-limit" : "pdfjs-find-match-count");
4929       findResultsCount.setAttribute("data-l10n-args", JSON.stringify({
4930         limit,
4931         current,
4932         total
4933       }));
4934     } else {
4935       findResultsCount.removeAttribute("data-l10n-id");
4936       findResultsCount.textContent = "";
4937     }
4938   }
4939   open() {
4940     if (!this.opened) {
4941       this.#resizeObserver.observe(this.#mainContainer);
4942       this.#resizeObserver.observe(this.bar);
4943       this.opened = true;
4944       toggleExpandedBtn(this.toggleButton, true, this.bar);
4945     }
4946     this.findField.select();
4947     this.findField.focus();
4948   }
4949   close() {
4950     if (!this.opened) {
4951       return;
4952     }
4953     this.#resizeObserver.disconnect();
4954     this.opened = false;
4955     toggleExpandedBtn(this.toggleButton, false, this.bar);
4956     this.eventBus.dispatch("findbarclose", {
4957       source: this
4958     });
4959   }
4960   toggle() {
4961     if (this.opened) {
4962       this.close();
4963     } else {
4964       this.open();
4965     }
4966   }
4967   #resizeObserverCallback() {
4968     const {
4969       bar
4970     } = this;
4971     bar.classList.remove("wrapContainers");
4972     const findbarHeight = bar.clientHeight;
4973     const inputContainerHeight = bar.firstElementChild.clientHeight;
4974     if (findbarHeight > inputContainerHeight) {
4975       bar.classList.add("wrapContainers");
4976     }
4977   }
4980 ;// ./web/pdf_history.js
4983 const HASH_CHANGE_TIMEOUT = 1000;
4984 const POSITION_UPDATED_THRESHOLD = 50;
4985 const UPDATE_VIEWAREA_TIMEOUT = 1000;
4986 function getCurrentHash() {
4987   return document.location.hash;
4989 class PDFHistory {
4990   #eventAbortController = null;
4991   constructor({
4992     linkService,
4993     eventBus
4994   }) {
4995     this.linkService = linkService;
4996     this.eventBus = eventBus;
4997     this._initialized = false;
4998     this._fingerprint = "";
4999     this.reset();
5000     this.eventBus._on("pagesinit", () => {
5001       this._isPagesLoaded = false;
5002       this.eventBus._on("pagesloaded", evt => {
5003         this._isPagesLoaded = !!evt.pagesCount;
5004       }, {
5005         once: true
5006       });
5007     });
5008   }
5009   initialize({
5010     fingerprint,
5011     resetHistory = false,
5012     updateUrl = false
5013   }) {
5014     if (!fingerprint || typeof fingerprint !== "string") {
5015       console.error('PDFHistory.initialize: The "fingerprint" must be a non-empty string.');
5016       return;
5017     }
5018     if (this._initialized) {
5019       this.reset();
5020     }
5021     const reInitialized = this._fingerprint !== "" && this._fingerprint !== fingerprint;
5022     this._fingerprint = fingerprint;
5023     this._updateUrl = updateUrl === true;
5024     this._initialized = true;
5025     this.#bindEvents();
5026     const state = window.history.state;
5027     this._popStateInProgress = false;
5028     this._blockHashChange = 0;
5029     this._currentHash = getCurrentHash();
5030     this._numPositionUpdates = 0;
5031     this._uid = this._maxUid = 0;
5032     this._destination = null;
5033     this._position = null;
5034     if (!this.#isValidState(state, true) || resetHistory) {
5035       const {
5036         hash,
5037         page,
5038         rotation
5039       } = this.#parseCurrentHash(true);
5040       if (!hash || reInitialized || resetHistory) {
5041         this.#pushOrReplaceState(null, true);
5042         return;
5043       }
5044       this.#pushOrReplaceState({
5045         hash,
5046         page,
5047         rotation
5048       }, true);
5049       return;
5050     }
5051     const destination = state.destination;
5052     this.#updateInternalState(destination, state.uid, true);
5053     if (destination.rotation !== undefined) {
5054       this._initialRotation = destination.rotation;
5055     }
5056     if (destination.dest) {
5057       this._initialBookmark = JSON.stringify(destination.dest);
5058       this._destination.page = null;
5059     } else if (destination.hash) {
5060       this._initialBookmark = destination.hash;
5061     } else if (destination.page) {
5062       this._initialBookmark = `page=${destination.page}`;
5063     }
5064   }
5065   reset() {
5066     if (this._initialized) {
5067       this.#pageHide();
5068       this._initialized = false;
5069       this.#unbindEvents();
5070     }
5071     if (this._updateViewareaTimeout) {
5072       clearTimeout(this._updateViewareaTimeout);
5073       this._updateViewareaTimeout = null;
5074     }
5075     this._initialBookmark = null;
5076     this._initialRotation = null;
5077   }
5078   push({
5079     namedDest = null,
5080     explicitDest,
5081     pageNumber
5082   }) {
5083     if (!this._initialized) {
5084       return;
5085     }
5086     if (namedDest && typeof namedDest !== "string") {
5087       console.error("PDFHistory.push: " + `"${namedDest}" is not a valid namedDest parameter.`);
5088       return;
5089     } else if (!Array.isArray(explicitDest)) {
5090       console.error("PDFHistory.push: " + `"${explicitDest}" is not a valid explicitDest parameter.`);
5091       return;
5092     } else if (!this.#isValidPage(pageNumber)) {
5093       if (pageNumber !== null || this._destination) {
5094         console.error("PDFHistory.push: " + `"${pageNumber}" is not a valid pageNumber parameter.`);
5095         return;
5096       }
5097     }
5098     const hash = namedDest || JSON.stringify(explicitDest);
5099     if (!hash) {
5100       return;
5101     }
5102     let forceReplace = false;
5103     if (this._destination && (isDestHashesEqual(this._destination.hash, hash) || isDestArraysEqual(this._destination.dest, explicitDest))) {
5104       if (this._destination.page) {
5105         return;
5106       }
5107       forceReplace = true;
5108     }
5109     if (this._popStateInProgress && !forceReplace) {
5110       return;
5111     }
5112     this.#pushOrReplaceState({
5113       dest: explicitDest,
5114       hash,
5115       page: pageNumber,
5116       rotation: this.linkService.rotation
5117     }, forceReplace);
5118     if (!this._popStateInProgress) {
5119       this._popStateInProgress = true;
5120       Promise.resolve().then(() => {
5121         this._popStateInProgress = false;
5122       });
5123     }
5124   }
5125   pushPage(pageNumber) {
5126     if (!this._initialized) {
5127       return;
5128     }
5129     if (!this.#isValidPage(pageNumber)) {
5130       console.error(`PDFHistory.pushPage: "${pageNumber}" is not a valid page number.`);
5131       return;
5132     }
5133     if (this._destination?.page === pageNumber) {
5134       return;
5135     }
5136     if (this._popStateInProgress) {
5137       return;
5138     }
5139     this.#pushOrReplaceState({
5140       dest: null,
5141       hash: `page=${pageNumber}`,
5142       page: pageNumber,
5143       rotation: this.linkService.rotation
5144     });
5145     if (!this._popStateInProgress) {
5146       this._popStateInProgress = true;
5147       Promise.resolve().then(() => {
5148         this._popStateInProgress = false;
5149       });
5150     }
5151   }
5152   pushCurrentPosition() {
5153     if (!this._initialized || this._popStateInProgress) {
5154       return;
5155     }
5156     this.#tryPushCurrentPosition();
5157   }
5158   back() {
5159     if (!this._initialized || this._popStateInProgress) {
5160       return;
5161     }
5162     const state = window.history.state;
5163     if (this.#isValidState(state) && state.uid > 0) {
5164       window.history.back();
5165     }
5166   }
5167   forward() {
5168     if (!this._initialized || this._popStateInProgress) {
5169       return;
5170     }
5171     const state = window.history.state;
5172     if (this.#isValidState(state) && state.uid < this._maxUid) {
5173       window.history.forward();
5174     }
5175   }
5176   get popStateInProgress() {
5177     return this._initialized && (this._popStateInProgress || this._blockHashChange > 0);
5178   }
5179   get initialBookmark() {
5180     return this._initialized ? this._initialBookmark : null;
5181   }
5182   get initialRotation() {
5183     return this._initialized ? this._initialRotation : null;
5184   }
5185   #pushOrReplaceState(destination, forceReplace = false) {
5186     const shouldReplace = forceReplace || !this._destination;
5187     const newState = {
5188       fingerprint: this._fingerprint,
5189       uid: shouldReplace ? this._uid : this._uid + 1,
5190       destination
5191     };
5192     this.#updateInternalState(destination, newState.uid);
5193     let newUrl;
5194     if (this._updateUrl && destination?.hash) {
5195       const baseUrl = document.location.href.split("#", 1)[0];
5196       if (!baseUrl.startsWith("file://")) {
5197         newUrl = `${baseUrl}#${destination.hash}`;
5198       }
5199     }
5200     if (shouldReplace) {
5201       window.history.replaceState(newState, "", newUrl);
5202     } else {
5203       window.history.pushState(newState, "", newUrl);
5204     }
5205   }
5206   #tryPushCurrentPosition(temporary = false) {
5207     if (!this._position) {
5208       return;
5209     }
5210     let position = this._position;
5211     if (temporary) {
5212       position = Object.assign(Object.create(null), this._position);
5213       position.temporary = true;
5214     }
5215     if (!this._destination) {
5216       this.#pushOrReplaceState(position);
5217       return;
5218     }
5219     if (this._destination.temporary) {
5220       this.#pushOrReplaceState(position, true);
5221       return;
5222     }
5223     if (this._destination.hash === position.hash) {
5224       return;
5225     }
5226     if (!this._destination.page && (POSITION_UPDATED_THRESHOLD <= 0 || this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)) {
5227       return;
5228     }
5229     let forceReplace = false;
5230     if (this._destination.page >= position.first && this._destination.page <= position.page) {
5231       if (this._destination.dest !== undefined || !this._destination.first) {
5232         return;
5233       }
5234       forceReplace = true;
5235     }
5236     this.#pushOrReplaceState(position, forceReplace);
5237   }
5238   #isValidPage(val) {
5239     return Number.isInteger(val) && val > 0 && val <= this.linkService.pagesCount;
5240   }
5241   #isValidState(state, checkReload = false) {
5242     if (!state) {
5243       return false;
5244     }
5245     if (state.fingerprint !== this._fingerprint) {
5246       if (checkReload) {
5247         if (typeof state.fingerprint !== "string" || state.fingerprint.length !== this._fingerprint.length) {
5248           return false;
5249         }
5250         const [perfEntry] = performance.getEntriesByType("navigation");
5251         if (perfEntry?.type !== "reload") {
5252           return false;
5253         }
5254       } else {
5255         return false;
5256       }
5257     }
5258     if (!Number.isInteger(state.uid) || state.uid < 0) {
5259       return false;
5260     }
5261     if (state.destination === null || typeof state.destination !== "object") {
5262       return false;
5263     }
5264     return true;
5265   }
5266   #updateInternalState(destination, uid, removeTemporary = false) {
5267     if (this._updateViewareaTimeout) {
5268       clearTimeout(this._updateViewareaTimeout);
5269       this._updateViewareaTimeout = null;
5270     }
5271     if (removeTemporary && destination?.temporary) {
5272       delete destination.temporary;
5273     }
5274     this._destination = destination;
5275     this._uid = uid;
5276     this._maxUid = Math.max(this._maxUid, uid);
5277     this._numPositionUpdates = 0;
5278   }
5279   #parseCurrentHash(checkNameddest = false) {
5280     const hash = unescape(getCurrentHash()).substring(1);
5281     const params = parseQueryString(hash);
5282     const nameddest = params.get("nameddest") || "";
5283     let page = params.get("page") | 0;
5284     if (!this.#isValidPage(page) || checkNameddest && nameddest.length > 0) {
5285       page = null;
5286     }
5287     return {
5288       hash,
5289       page,
5290       rotation: this.linkService.rotation
5291     };
5292   }
5293   #updateViewarea({
5294     location
5295   }) {
5296     if (this._updateViewareaTimeout) {
5297       clearTimeout(this._updateViewareaTimeout);
5298       this._updateViewareaTimeout = null;
5299     }
5300     this._position = {
5301       hash: location.pdfOpenParams.substring(1),
5302       page: this.linkService.page,
5303       first: location.pageNumber,
5304       rotation: location.rotation
5305     };
5306     if (this._popStateInProgress) {
5307       return;
5308     }
5309     if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) {
5310       this._numPositionUpdates++;
5311     }
5312     if (UPDATE_VIEWAREA_TIMEOUT > 0) {
5313       this._updateViewareaTimeout = setTimeout(() => {
5314         if (!this._popStateInProgress) {
5315           this.#tryPushCurrentPosition(true);
5316         }
5317         this._updateViewareaTimeout = null;
5318       }, UPDATE_VIEWAREA_TIMEOUT);
5319     }
5320   }
5321   #popState({
5322     state
5323   }) {
5324     const newHash = getCurrentHash(),
5325       hashChanged = this._currentHash !== newHash;
5326     this._currentHash = newHash;
5327     if (!state) {
5328       this._uid++;
5329       const {
5330         hash,
5331         page,
5332         rotation
5333       } = this.#parseCurrentHash();
5334       this.#pushOrReplaceState({
5335         hash,
5336         page,
5337         rotation
5338       }, true);
5339       return;
5340     }
5341     if (!this.#isValidState(state)) {
5342       return;
5343     }
5344     this._popStateInProgress = true;
5345     if (hashChanged) {
5346       this._blockHashChange++;
5347       waitOnEventOrTimeout({
5348         target: window,
5349         name: "hashchange",
5350         delay: HASH_CHANGE_TIMEOUT
5351       }).then(() => {
5352         this._blockHashChange--;
5353       });
5354     }
5355     const destination = state.destination;
5356     this.#updateInternalState(destination, state.uid, true);
5357     if (isValidRotation(destination.rotation)) {
5358       this.linkService.rotation = destination.rotation;
5359     }
5360     if (destination.dest) {
5361       this.linkService.goToDestination(destination.dest);
5362     } else if (destination.hash) {
5363       this.linkService.setHash(destination.hash);
5364     } else if (destination.page) {
5365       this.linkService.page = destination.page;
5366     }
5367     Promise.resolve().then(() => {
5368       this._popStateInProgress = false;
5369     });
5370   }
5371   #pageHide() {
5372     if (!this._destination || this._destination.temporary) {
5373       this.#tryPushCurrentPosition();
5374     }
5375   }
5376   #bindEvents() {
5377     if (this.#eventAbortController) {
5378       return;
5379     }
5380     this.#eventAbortController = new AbortController();
5381     const {
5382       signal
5383     } = this.#eventAbortController;
5384     this.eventBus._on("updateviewarea", this.#updateViewarea.bind(this), {
5385       signal
5386     });
5387     window.addEventListener("popstate", this.#popState.bind(this), {
5388       signal
5389     });
5390     window.addEventListener("pagehide", this.#pageHide.bind(this), {
5391       signal
5392     });
5393   }
5394   #unbindEvents() {
5395     this.#eventAbortController?.abort();
5396     this.#eventAbortController = null;
5397   }
5399 function isDestHashesEqual(destHash, pushHash) {
5400   if (typeof destHash !== "string" || typeof pushHash !== "string") {
5401     return false;
5402   }
5403   if (destHash === pushHash) {
5404     return true;
5405   }
5406   const nameddest = parseQueryString(destHash).get("nameddest");
5407   if (nameddest === pushHash) {
5408     return true;
5409   }
5410   return false;
5412 function isDestArraysEqual(firstDest, secondDest) {
5413   function isEntryEqual(first, second) {
5414     if (typeof first !== typeof second) {
5415       return false;
5416     }
5417     if (Array.isArray(first) || Array.isArray(second)) {
5418       return false;
5419     }
5420     if (first !== null && typeof first === "object" && second !== null) {
5421       if (Object.keys(first).length !== Object.keys(second).length) {
5422         return false;
5423       }
5424       for (const key in first) {
5425         if (!isEntryEqual(first[key], second[key])) {
5426           return false;
5427         }
5428       }
5429       return true;
5430     }
5431     return first === second || Number.isNaN(first) && Number.isNaN(second);
5432   }
5433   if (!(Array.isArray(firstDest) && Array.isArray(secondDest))) {
5434     return false;
5435   }
5436   if (firstDest.length !== secondDest.length) {
5437     return false;
5438   }
5439   for (let i = 0, ii = firstDest.length; i < ii; i++) {
5440     if (!isEntryEqual(firstDest[i], secondDest[i])) {
5441       return false;
5442     }
5443   }
5444   return true;
5447 ;// ./web/pdf_layer_viewer.js
5449 class PDFLayerViewer extends BaseTreeViewer {
5450   constructor(options) {
5451     super(options);
5452     this.eventBus._on("optionalcontentconfigchanged", evt => {
5453       this.#updateLayers(evt.promise);
5454     });
5455     this.eventBus._on("resetlayers", () => {
5456       this.#updateLayers();
5457     });
5458     this.eventBus._on("togglelayerstree", this._toggleAllTreeItems.bind(this));
5459   }
5460   reset() {
5461     super.reset();
5462     this._optionalContentConfig = null;
5463     this._optionalContentVisibility?.clear();
5464     this._optionalContentVisibility = null;
5465   }
5466   _dispatchEvent(layersCount) {
5467     this.eventBus.dispatch("layersloaded", {
5468       source: this,
5469       layersCount
5470     });
5471   }
5472   _bindLink(element, {
5473     groupId,
5474     input
5475   }) {
5476     const setVisibility = () => {
5477       const visible = input.checked;
5478       this._optionalContentConfig.setVisibility(groupId, visible);
5479       const cached = this._optionalContentVisibility.get(groupId);
5480       if (cached) {
5481         cached.visible = visible;
5482       }
5483       this.eventBus.dispatch("optionalcontentconfig", {
5484         source: this,
5485         promise: Promise.resolve(this._optionalContentConfig)
5486       });
5487     };
5488     element.onclick = evt => {
5489       if (evt.target === input) {
5490         setVisibility();
5491         return true;
5492       } else if (evt.target !== element) {
5493         return true;
5494       }
5495       input.checked = !input.checked;
5496       setVisibility();
5497       return false;
5498     };
5499   }
5500   _setNestedName(element, {
5501     name = null
5502   }) {
5503     if (typeof name === "string") {
5504       element.textContent = this._normalizeTextContent(name);
5505       return;
5506     }
5507     element.setAttribute("data-l10n-id", "pdfjs-additional-layers");
5508     element.style.fontStyle = "italic";
5509     this._l10n.translateOnce(element);
5510   }
5511   _addToggleButton(div, {
5512     name = null
5513   }) {
5514     super._addToggleButton(div, name === null);
5515   }
5516   _toggleAllTreeItems() {
5517     if (!this._optionalContentConfig) {
5518       return;
5519     }
5520     super._toggleAllTreeItems();
5521   }
5522   render({
5523     optionalContentConfig,
5524     pdfDocument
5525   }) {
5526     if (this._optionalContentConfig) {
5527       this.reset();
5528     }
5529     this._optionalContentConfig = optionalContentConfig || null;
5530     this._pdfDocument = pdfDocument || null;
5531     const groups = optionalContentConfig?.getOrder();
5532     if (!groups) {
5533       this._dispatchEvent(0);
5534       return;
5535     }
5536     this._optionalContentVisibility = new Map();
5537     const fragment = document.createDocumentFragment(),
5538       queue = [{
5539         parent: fragment,
5540         groups
5541       }];
5542     let layersCount = 0,
5543       hasAnyNesting = false;
5544     while (queue.length > 0) {
5545       const levelData = queue.shift();
5546       for (const groupId of levelData.groups) {
5547         const div = document.createElement("div");
5548         div.className = "treeItem";
5549         const element = document.createElement("a");
5550         div.append(element);
5551         if (typeof groupId === "object") {
5552           hasAnyNesting = true;
5553           this._addToggleButton(div, groupId);
5554           this._setNestedName(element, groupId);
5555           const itemsDiv = document.createElement("div");
5556           itemsDiv.className = "treeItems";
5557           div.append(itemsDiv);
5558           queue.push({
5559             parent: itemsDiv,
5560             groups: groupId.order
5561           });
5562         } else {
5563           const group = optionalContentConfig.getGroup(groupId);
5564           const input = document.createElement("input");
5565           this._bindLink(element, {
5566             groupId,
5567             input
5568           });
5569           input.type = "checkbox";
5570           input.checked = group.visible;
5571           this._optionalContentVisibility.set(groupId, {
5572             input,
5573             visible: input.checked
5574           });
5575           const label = document.createElement("label");
5576           label.textContent = this._normalizeTextContent(group.name);
5577           label.append(input);
5578           element.append(label);
5579           layersCount++;
5580         }
5581         levelData.parent.append(div);
5582       }
5583     }
5584     this._finishRendering(fragment, layersCount, hasAnyNesting);
5585   }
5586   async #updateLayers(promise = null) {
5587     if (!this._optionalContentConfig) {
5588       return;
5589     }
5590     const pdfDocument = this._pdfDocument;
5591     const optionalContentConfig = await (promise || pdfDocument.getOptionalContentConfig({
5592       intent: "display"
5593     }));
5594     if (pdfDocument !== this._pdfDocument) {
5595       return;
5596     }
5597     if (promise) {
5598       for (const [groupId, cached] of this._optionalContentVisibility) {
5599         const group = optionalContentConfig.getGroup(groupId);
5600         if (group && cached.visible !== group.visible) {
5601           cached.input.checked = cached.visible = !cached.visible;
5602         }
5603       }
5604       return;
5605     }
5606     this.eventBus.dispatch("optionalcontentconfig", {
5607       source: this,
5608       promise: Promise.resolve(optionalContentConfig)
5609     });
5610     this.render({
5611       optionalContentConfig,
5612       pdfDocument: this._pdfDocument
5613     });
5614   }
5617 ;// ./web/pdf_outline_viewer.js
5620 class PDFOutlineViewer extends BaseTreeViewer {
5621   constructor(options) {
5622     super(options);
5623     this.linkService = options.linkService;
5624     this.downloadManager = options.downloadManager;
5625     this.eventBus._on("toggleoutlinetree", this._toggleAllTreeItems.bind(this));
5626     this.eventBus._on("currentoutlineitem", this._currentOutlineItem.bind(this));
5627     this.eventBus._on("pagechanging", evt => {
5628       this._currentPageNumber = evt.pageNumber;
5629     });
5630     this.eventBus._on("pagesloaded", evt => {
5631       this._isPagesLoaded = !!evt.pagesCount;
5632       this._currentOutlineItemCapability?.resolve(this._isPagesLoaded);
5633     });
5634     this.eventBus._on("sidebarviewchanged", evt => {
5635       this._sidebarView = evt.view;
5636     });
5637   }
5638   reset() {
5639     super.reset();
5640     this._outline = null;
5641     this._pageNumberToDestHashCapability = null;
5642     this._currentPageNumber = 1;
5643     this._isPagesLoaded = null;
5644     this._currentOutlineItemCapability?.resolve(false);
5645     this._currentOutlineItemCapability = null;
5646   }
5647   _dispatchEvent(outlineCount) {
5648     this._currentOutlineItemCapability = Promise.withResolvers();
5649     if (outlineCount === 0 || this._pdfDocument?.loadingParams.disableAutoFetch) {
5650       this._currentOutlineItemCapability.resolve(false);
5651     } else if (this._isPagesLoaded !== null) {
5652       this._currentOutlineItemCapability.resolve(this._isPagesLoaded);
5653     }
5654     this.eventBus.dispatch("outlineloaded", {
5655       source: this,
5656       outlineCount,
5657       currentOutlineItemPromise: this._currentOutlineItemCapability.promise
5658     });
5659   }
5660   _bindLink(element, {
5661     url,
5662     newWindow,
5663     action,
5664     attachment,
5665     dest,
5666     setOCGState
5667   }) {
5668     const {
5669       linkService
5670     } = this;
5671     if (url) {
5672       linkService.addLinkAttributes(element, url, newWindow);
5673       return;
5674     }
5675     if (action) {
5676       element.href = linkService.getAnchorUrl("");
5677       element.onclick = () => {
5678         linkService.executeNamedAction(action);
5679         return false;
5680       };
5681       return;
5682     }
5683     if (attachment) {
5684       element.href = linkService.getAnchorUrl("");
5685       element.onclick = () => {
5686         this.downloadManager.openOrDownloadData(attachment.content, attachment.filename);
5687         return false;
5688       };
5689       return;
5690     }
5691     if (setOCGState) {
5692       element.href = linkService.getAnchorUrl("");
5693       element.onclick = () => {
5694         linkService.executeSetOCGState(setOCGState);
5695         return false;
5696       };
5697       return;
5698     }
5699     element.href = linkService.getDestinationHash(dest);
5700     element.onclick = evt => {
5701       this._updateCurrentTreeItem(evt.target.parentNode);
5702       if (dest) {
5703         linkService.goToDestination(dest);
5704       }
5705       return false;
5706     };
5707   }
5708   _setStyles(element, {
5709     bold,
5710     italic
5711   }) {
5712     if (bold) {
5713       element.style.fontWeight = "bold";
5714     }
5715     if (italic) {
5716       element.style.fontStyle = "italic";
5717     }
5718   }
5719   _addToggleButton(div, {
5720     count,
5721     items
5722   }) {
5723     let hidden = false;
5724     if (count < 0) {
5725       let totalCount = items.length;
5726       if (totalCount > 0) {
5727         const queue = [...items];
5728         while (queue.length > 0) {
5729           const {
5730             count: nestedCount,
5731             items: nestedItems
5732           } = queue.shift();
5733           if (nestedCount > 0 && nestedItems.length > 0) {
5734             totalCount += nestedItems.length;
5735             queue.push(...nestedItems);
5736           }
5737         }
5738       }
5739       if (Math.abs(count) === totalCount) {
5740         hidden = true;
5741       }
5742     }
5743     super._addToggleButton(div, hidden);
5744   }
5745   _toggleAllTreeItems() {
5746     if (!this._outline) {
5747       return;
5748     }
5749     super._toggleAllTreeItems();
5750   }
5751   render({
5752     outline,
5753     pdfDocument
5754   }) {
5755     if (this._outline) {
5756       this.reset();
5757     }
5758     this._outline = outline || null;
5759     this._pdfDocument = pdfDocument || null;
5760     if (!outline) {
5761       this._dispatchEvent(0);
5762       return;
5763     }
5764     const fragment = document.createDocumentFragment();
5765     const queue = [{
5766       parent: fragment,
5767       items: outline
5768     }];
5769     let outlineCount = 0,
5770       hasAnyNesting = false;
5771     while (queue.length > 0) {
5772       const levelData = queue.shift();
5773       for (const item of levelData.items) {
5774         const div = document.createElement("div");
5775         div.className = "treeItem";
5776         const element = document.createElement("a");
5777         this._bindLink(element, item);
5778         this._setStyles(element, item);
5779         element.textContent = this._normalizeTextContent(item.title);
5780         div.append(element);
5781         if (item.items.length > 0) {
5782           hasAnyNesting = true;
5783           this._addToggleButton(div, item);
5784           const itemsDiv = document.createElement("div");
5785           itemsDiv.className = "treeItems";
5786           div.append(itemsDiv);
5787           queue.push({
5788             parent: itemsDiv,
5789             items: item.items
5790           });
5791         }
5792         levelData.parent.append(div);
5793         outlineCount++;
5794       }
5795     }
5796     this._finishRendering(fragment, outlineCount, hasAnyNesting);
5797   }
5798   async _currentOutlineItem() {
5799     if (!this._isPagesLoaded) {
5800       throw new Error("_currentOutlineItem: All pages have not been loaded.");
5801     }
5802     if (!this._outline || !this._pdfDocument) {
5803       return;
5804     }
5805     const pageNumberToDestHash = await this._getPageNumberToDestHash(this._pdfDocument);
5806     if (!pageNumberToDestHash) {
5807       return;
5808     }
5809     this._updateCurrentTreeItem(null);
5810     if (this._sidebarView !== SidebarView.OUTLINE) {
5811       return;
5812     }
5813     for (let i = this._currentPageNumber; i > 0; i--) {
5814       const destHash = pageNumberToDestHash.get(i);
5815       if (!destHash) {
5816         continue;
5817       }
5818       const linkElement = this.container.querySelector(`a[href="${destHash}"]`);
5819       if (!linkElement) {
5820         continue;
5821       }
5822       this._scrollToCurrentTreeItem(linkElement.parentNode);
5823       break;
5824     }
5825   }
5826   async _getPageNumberToDestHash(pdfDocument) {
5827     if (this._pageNumberToDestHashCapability) {
5828       return this._pageNumberToDestHashCapability.promise;
5829     }
5830     this._pageNumberToDestHashCapability = Promise.withResolvers();
5831     const pageNumberToDestHash = new Map(),
5832       pageNumberNesting = new Map();
5833     const queue = [{
5834       nesting: 0,
5835       items: this._outline
5836     }];
5837     while (queue.length > 0) {
5838       const levelData = queue.shift(),
5839         currentNesting = levelData.nesting;
5840       for (const {
5841         dest,
5842         items
5843       } of levelData.items) {
5844         let explicitDest, pageNumber;
5845         if (typeof dest === "string") {
5846           explicitDest = await pdfDocument.getDestination(dest);
5847           if (pdfDocument !== this._pdfDocument) {
5848             return null;
5849           }
5850         } else {
5851           explicitDest = dest;
5852         }
5853         if (Array.isArray(explicitDest)) {
5854           const [destRef] = explicitDest;
5855           if (destRef && typeof destRef === "object") {
5856             pageNumber = pdfDocument.cachedPageNumber(destRef);
5857           } else if (Number.isInteger(destRef)) {
5858             pageNumber = destRef + 1;
5859           }
5860           if (Number.isInteger(pageNumber) && (!pageNumberToDestHash.has(pageNumber) || currentNesting > pageNumberNesting.get(pageNumber))) {
5861             const destHash = this.linkService.getDestinationHash(dest);
5862             pageNumberToDestHash.set(pageNumber, destHash);
5863             pageNumberNesting.set(pageNumber, currentNesting);
5864           }
5865         }
5866         if (items.length > 0) {
5867           queue.push({
5868             nesting: currentNesting + 1,
5869             items
5870           });
5871         }
5872       }
5873     }
5874     this._pageNumberToDestHashCapability.resolve(pageNumberToDestHash.size > 0 ? pageNumberToDestHash : null);
5875     return this._pageNumberToDestHashCapability.promise;
5876   }
5879 ;// ./web/pdf_presentation_mode.js
5882 const DELAY_BEFORE_HIDING_CONTROLS = 3000;
5883 const ACTIVE_SELECTOR = "pdfPresentationMode";
5884 const CONTROLS_SELECTOR = "pdfPresentationModeControls";
5885 const MOUSE_SCROLL_COOLDOWN_TIME = 50;
5886 const PAGE_SWITCH_THRESHOLD = 0.1;
5887 const SWIPE_MIN_DISTANCE_THRESHOLD = 50;
5888 const SWIPE_ANGLE_THRESHOLD = Math.PI / 6;
5889 class PDFPresentationMode {
5890   #state = PresentationModeState.UNKNOWN;
5891   #args = null;
5892   #fullscreenChangeAbortController = null;
5893   #windowAbortController = null;
5894   constructor({
5895     container,
5896     pdfViewer,
5897     eventBus
5898   }) {
5899     this.container = container;
5900     this.pdfViewer = pdfViewer;
5901     this.eventBus = eventBus;
5902     this.contextMenuOpen = false;
5903     this.mouseScrollTimeStamp = 0;
5904     this.mouseScrollDelta = 0;
5905     this.touchSwipeState = null;
5906   }
5907   async request() {
5908     const {
5909       container,
5910       pdfViewer
5911     } = this;
5912     if (this.active || !pdfViewer.pagesCount || !container.requestFullscreen) {
5913       return false;
5914     }
5915     this.#addFullscreenChangeListeners();
5916     this.#notifyStateChange(PresentationModeState.CHANGING);
5917     const promise = container.requestFullscreen();
5918     this.#args = {
5919       pageNumber: pdfViewer.currentPageNumber,
5920       scaleValue: pdfViewer.currentScaleValue,
5921       scrollMode: pdfViewer.scrollMode,
5922       spreadMode: null,
5923       annotationEditorMode: null
5924     };
5925     if (pdfViewer.spreadMode !== SpreadMode.NONE && !(pdfViewer.pageViewsReady && pdfViewer.hasEqualPageSizes)) {
5926       console.warn("Ignoring Spread modes when entering PresentationMode, " + "since the document may contain varying page sizes.");
5927       this.#args.spreadMode = pdfViewer.spreadMode;
5928     }
5929     if (pdfViewer.annotationEditorMode !== AnnotationEditorType.DISABLE) {
5930       this.#args.annotationEditorMode = pdfViewer.annotationEditorMode;
5931     }
5932     try {
5933       await promise;
5934       pdfViewer.focus();
5935       return true;
5936     } catch {
5937       this.#removeFullscreenChangeListeners();
5938       this.#notifyStateChange(PresentationModeState.NORMAL);
5939     }
5940     return false;
5941   }
5942   get active() {
5943     return this.#state === PresentationModeState.CHANGING || this.#state === PresentationModeState.FULLSCREEN;
5944   }
5945   #mouseWheel(evt) {
5946     if (!this.active) {
5947       return;
5948     }
5949     evt.preventDefault();
5950     const delta = normalizeWheelEventDelta(evt);
5951     const currentTime = Date.now();
5952     const storedTime = this.mouseScrollTimeStamp;
5953     if (currentTime > storedTime && currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) {
5954       return;
5955     }
5956     if (this.mouseScrollDelta > 0 && delta < 0 || this.mouseScrollDelta < 0 && delta > 0) {
5957       this.#resetMouseScrollState();
5958     }
5959     this.mouseScrollDelta += delta;
5960     if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) {
5961       const totalDelta = this.mouseScrollDelta;
5962       this.#resetMouseScrollState();
5963       const success = totalDelta > 0 ? this.pdfViewer.previousPage() : this.pdfViewer.nextPage();
5964       if (success) {
5965         this.mouseScrollTimeStamp = currentTime;
5966       }
5967     }
5968   }
5969   #notifyStateChange(state) {
5970     this.#state = state;
5971     this.eventBus.dispatch("presentationmodechanged", {
5972       source: this,
5973       state
5974     });
5975   }
5976   #enter() {
5977     this.#notifyStateChange(PresentationModeState.FULLSCREEN);
5978     this.container.classList.add(ACTIVE_SELECTOR);
5979     setTimeout(() => {
5980       this.pdfViewer.scrollMode = ScrollMode.PAGE;
5981       if (this.#args.spreadMode !== null) {
5982         this.pdfViewer.spreadMode = SpreadMode.NONE;
5983       }
5984       this.pdfViewer.currentPageNumber = this.#args.pageNumber;
5985       this.pdfViewer.currentScaleValue = "page-fit";
5986       if (this.#args.annotationEditorMode !== null) {
5987         this.pdfViewer.annotationEditorMode = {
5988           mode: AnnotationEditorType.NONE
5989         };
5990       }
5991     }, 0);
5992     this.#addWindowListeners();
5993     this.#showControls();
5994     this.contextMenuOpen = false;
5995     document.getSelection().empty();
5996   }
5997   #exit() {
5998     const pageNumber = this.pdfViewer.currentPageNumber;
5999     this.container.classList.remove(ACTIVE_SELECTOR);
6000     setTimeout(() => {
6001       this.#removeFullscreenChangeListeners();
6002       this.#notifyStateChange(PresentationModeState.NORMAL);
6003       this.pdfViewer.scrollMode = this.#args.scrollMode;
6004       if (this.#args.spreadMode !== null) {
6005         this.pdfViewer.spreadMode = this.#args.spreadMode;
6006       }
6007       this.pdfViewer.currentScaleValue = this.#args.scaleValue;
6008       this.pdfViewer.currentPageNumber = pageNumber;
6009       if (this.#args.annotationEditorMode !== null) {
6010         this.pdfViewer.annotationEditorMode = {
6011           mode: this.#args.annotationEditorMode
6012         };
6013       }
6014       this.#args = null;
6015     }, 0);
6016     this.#removeWindowListeners();
6017     this.#hideControls();
6018     this.#resetMouseScrollState();
6019     this.contextMenuOpen = false;
6020   }
6021   #mouseDown(evt) {
6022     if (this.contextMenuOpen) {
6023       this.contextMenuOpen = false;
6024       evt.preventDefault();
6025       return;
6026     }
6027     if (evt.button !== 0) {
6028       return;
6029     }
6030     if (evt.target.href && evt.target.parentNode?.hasAttribute("data-internal-link")) {
6031       return;
6032     }
6033     evt.preventDefault();
6034     if (evt.shiftKey) {
6035       this.pdfViewer.previousPage();
6036     } else {
6037       this.pdfViewer.nextPage();
6038     }
6039   }
6040   #contextMenu() {
6041     this.contextMenuOpen = true;
6042   }
6043   #showControls() {
6044     if (this.controlsTimeout) {
6045       clearTimeout(this.controlsTimeout);
6046     } else {
6047       this.container.classList.add(CONTROLS_SELECTOR);
6048     }
6049     this.controlsTimeout = setTimeout(() => {
6050       this.container.classList.remove(CONTROLS_SELECTOR);
6051       delete this.controlsTimeout;
6052     }, DELAY_BEFORE_HIDING_CONTROLS);
6053   }
6054   #hideControls() {
6055     if (!this.controlsTimeout) {
6056       return;
6057     }
6058     clearTimeout(this.controlsTimeout);
6059     this.container.classList.remove(CONTROLS_SELECTOR);
6060     delete this.controlsTimeout;
6061   }
6062   #resetMouseScrollState() {
6063     this.mouseScrollTimeStamp = 0;
6064     this.mouseScrollDelta = 0;
6065   }
6066   #touchSwipe(evt) {
6067     if (!this.active) {
6068       return;
6069     }
6070     if (evt.touches.length > 1) {
6071       this.touchSwipeState = null;
6072       return;
6073     }
6074     switch (evt.type) {
6075       case "touchstart":
6076         this.touchSwipeState = {
6077           startX: evt.touches[0].pageX,
6078           startY: evt.touches[0].pageY,
6079           endX: evt.touches[0].pageX,
6080           endY: evt.touches[0].pageY
6081         };
6082         break;
6083       case "touchmove":
6084         if (this.touchSwipeState === null) {
6085           return;
6086         }
6087         this.touchSwipeState.endX = evt.touches[0].pageX;
6088         this.touchSwipeState.endY = evt.touches[0].pageY;
6089         evt.preventDefault();
6090         break;
6091       case "touchend":
6092         if (this.touchSwipeState === null) {
6093           return;
6094         }
6095         let delta = 0;
6096         const dx = this.touchSwipeState.endX - this.touchSwipeState.startX;
6097         const dy = this.touchSwipeState.endY - this.touchSwipeState.startY;
6098         const absAngle = Math.abs(Math.atan2(dy, dx));
6099         if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD && (absAngle <= SWIPE_ANGLE_THRESHOLD || absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) {
6100           delta = dx;
6101         } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD && Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) {
6102           delta = dy;
6103         }
6104         if (delta > 0) {
6105           this.pdfViewer.previousPage();
6106         } else if (delta < 0) {
6107           this.pdfViewer.nextPage();
6108         }
6109         break;
6110     }
6111   }
6112   #addWindowListeners() {
6113     if (this.#windowAbortController) {
6114       return;
6115     }
6116     this.#windowAbortController = new AbortController();
6117     const {
6118       signal
6119     } = this.#windowAbortController;
6120     const touchSwipeBind = this.#touchSwipe.bind(this);
6121     window.addEventListener("mousemove", this.#showControls.bind(this), {
6122       signal
6123     });
6124     window.addEventListener("mousedown", this.#mouseDown.bind(this), {
6125       signal
6126     });
6127     window.addEventListener("wheel", this.#mouseWheel.bind(this), {
6128       passive: false,
6129       signal
6130     });
6131     window.addEventListener("keydown", this.#resetMouseScrollState.bind(this), {
6132       signal
6133     });
6134     window.addEventListener("contextmenu", this.#contextMenu.bind(this), {
6135       signal
6136     });
6137     window.addEventListener("touchstart", touchSwipeBind, {
6138       signal
6139     });
6140     window.addEventListener("touchmove", touchSwipeBind, {
6141       signal
6142     });
6143     window.addEventListener("touchend", touchSwipeBind, {
6144       signal
6145     });
6146   }
6147   #removeWindowListeners() {
6148     this.#windowAbortController?.abort();
6149     this.#windowAbortController = null;
6150   }
6151   #addFullscreenChangeListeners() {
6152     if (this.#fullscreenChangeAbortController) {
6153       return;
6154     }
6155     this.#fullscreenChangeAbortController = new AbortController();
6156     window.addEventListener("fullscreenchange", () => {
6157       if (document.fullscreenElement) {
6158         this.#enter();
6159       } else {
6160         this.#exit();
6161       }
6162     }, {
6163       signal: this.#fullscreenChangeAbortController.signal
6164     });
6165   }
6166   #removeFullscreenChangeListeners() {
6167     this.#fullscreenChangeAbortController?.abort();
6168     this.#fullscreenChangeAbortController = null;
6169   }
6172 ;// ./web/xfa_layer_builder.js
6174 class XfaLayerBuilder {
6175   constructor({
6176     pdfPage,
6177     annotationStorage = null,
6178     linkService,
6179     xfaHtml = null
6180   }) {
6181     this.pdfPage = pdfPage;
6182     this.annotationStorage = annotationStorage;
6183     this.linkService = linkService;
6184     this.xfaHtml = xfaHtml;
6185     this.div = null;
6186     this._cancelled = false;
6187   }
6188   async render({
6189     viewport,
6190     intent = "display"
6191   }) {
6192     if (intent === "print") {
6193       const parameters = {
6194         viewport: viewport.clone({
6195           dontFlip: true
6196         }),
6197         div: this.div,
6198         xfaHtml: this.xfaHtml,
6199         annotationStorage: this.annotationStorage,
6200         linkService: this.linkService,
6201         intent
6202       };
6203       this.div = document.createElement("div");
6204       parameters.div = this.div;
6205       return XfaLayer.render(parameters);
6206     }
6207     const xfaHtml = await this.pdfPage.getXfa();
6208     if (this._cancelled || !xfaHtml) {
6209       return {
6210         textDivs: []
6211       };
6212     }
6213     const parameters = {
6214       viewport: viewport.clone({
6215         dontFlip: true
6216       }),
6217       div: this.div,
6218       xfaHtml,
6219       annotationStorage: this.annotationStorage,
6220       linkService: this.linkService,
6221       intent
6222     };
6223     if (this.div) {
6224       return XfaLayer.update(parameters);
6225     }
6226     this.div = document.createElement("div");
6227     parameters.div = this.div;
6228     return XfaLayer.render(parameters);
6229   }
6230   cancel() {
6231     this._cancelled = true;
6232   }
6233   hide() {
6234     if (!this.div) {
6235       return;
6236     }
6237     this.div.hidden = true;
6238   }
6241 ;// ./web/print_utils.js
6245 function getXfaHtmlForPrinting(printContainer, pdfDocument) {
6246   const xfaHtml = pdfDocument.allXfaHtml;
6247   const linkService = new SimpleLinkService();
6248   const scale = Math.round(PixelsPerInch.PDF_TO_CSS_UNITS * 100) / 100;
6249   for (const xfaPage of xfaHtml.children) {
6250     const page = document.createElement("div");
6251     page.className = "xfaPrintedPage";
6252     printContainer.append(page);
6253     const builder = new XfaLayerBuilder({
6254       pdfPage: null,
6255       annotationStorage: pdfDocument.annotationStorage,
6256       linkService,
6257       xfaHtml: xfaPage
6258     });
6259     const viewport = getXfaPageViewport(xfaPage, {
6260       scale
6261     });
6262     builder.render(viewport, "print");
6263     page.append(builder.div);
6264   }
6267 ;// ./web/firefox_print_service.js
6270 function composePage(pdfDocument, pageNumber, size, printContainer, printResolution, optionalContentConfigPromise, printAnnotationStoragePromise) {
6271   const canvas = document.createElement("canvas");
6272   const PRINT_UNITS = printResolution / PixelsPerInch.PDF;
6273   canvas.width = Math.floor(size.width * PRINT_UNITS);
6274   canvas.height = Math.floor(size.height * PRINT_UNITS);
6275   const canvasWrapper = document.createElement("div");
6276   canvasWrapper.className = "printedPage";
6277   canvasWrapper.append(canvas);
6278   printContainer.append(canvasWrapper);
6279   let currentRenderTask = null;
6280   canvas.mozPrintCallback = function (obj) {
6281     const ctx = obj.context;
6282     ctx.save();
6283     ctx.fillStyle = "rgb(255, 255, 255)";
6284     ctx.fillRect(0, 0, canvas.width, canvas.height);
6285     ctx.restore();
6286     let thisRenderTask = null;
6287     Promise.all([pdfDocument.getPage(pageNumber), printAnnotationStoragePromise]).then(function ([pdfPage, printAnnotationStorage]) {
6288       if (currentRenderTask) {
6289         currentRenderTask.cancel();
6290         currentRenderTask = null;
6291       }
6292       const renderContext = {
6293         canvasContext: ctx,
6294         transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
6295         viewport: pdfPage.getViewport({
6296           scale: 1,
6297           rotation: size.rotation
6298         }),
6299         intent: "print",
6300         annotationMode: AnnotationMode.ENABLE_STORAGE,
6301         optionalContentConfigPromise,
6302         printAnnotationStorage
6303       };
6304       currentRenderTask = thisRenderTask = pdfPage.render(renderContext);
6305       return thisRenderTask.promise;
6306     }).then(function () {
6307       if (currentRenderTask === thisRenderTask) {
6308         currentRenderTask = null;
6309       }
6310       obj.done();
6311     }, function (reason) {
6312       if (!(reason instanceof RenderingCancelledException)) {
6313         console.error(reason);
6314       }
6315       if (currentRenderTask === thisRenderTask) {
6316         currentRenderTask.cancel();
6317         currentRenderTask = null;
6318       }
6319       if ("abort" in obj) {
6320         obj.abort();
6321       } else {
6322         obj.done();
6323       }
6324     });
6325   };
6327 class FirefoxPrintService {
6328   constructor({
6329     pdfDocument,
6330     pagesOverview,
6331     printContainer,
6332     printResolution,
6333     printAnnotationStoragePromise = null
6334   }) {
6335     this.pdfDocument = pdfDocument;
6336     this.pagesOverview = pagesOverview;
6337     this.printContainer = printContainer;
6338     this._printResolution = printResolution || 150;
6339     this._optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
6340       intent: "print"
6341     });
6342     this._printAnnotationStoragePromise = printAnnotationStoragePromise || Promise.resolve();
6343   }
6344   layout() {
6345     const {
6346       pdfDocument,
6347       pagesOverview,
6348       printContainer,
6349       _printResolution,
6350       _optionalContentConfigPromise,
6351       _printAnnotationStoragePromise
6352     } = this;
6353     const body = document.querySelector("body");
6354     body.setAttribute("data-pdfjsprinting", true);
6355     const {
6356       width,
6357       height
6358     } = this.pagesOverview[0];
6359     const hasEqualPageSizes = this.pagesOverview.every(size => size.width === width && size.height === height);
6360     if (!hasEqualPageSizes) {
6361       console.warn("Not all pages have the same size. The printed result may be incorrect!");
6362     }
6363     this.pageStyleSheet = document.createElement("style");
6364     this.pageStyleSheet.textContent = `@page { size: ${width}pt ${height}pt;}`;
6365     body.append(this.pageStyleSheet);
6366     if (pdfDocument.isPureXfa) {
6367       getXfaHtmlForPrinting(printContainer, pdfDocument);
6368       return;
6369     }
6370     for (let i = 0, ii = pagesOverview.length; i < ii; ++i) {
6371       composePage(pdfDocument, i + 1, pagesOverview[i], printContainer, _printResolution, _optionalContentConfigPromise, _printAnnotationStoragePromise);
6372     }
6373   }
6374   destroy() {
6375     this.printContainer.textContent = "";
6376     const body = document.querySelector("body");
6377     body.removeAttribute("data-pdfjsprinting");
6378     if (this.pageStyleSheet) {
6379       this.pageStyleSheet.remove();
6380       this.pageStyleSheet = null;
6381     }
6382   }
6384 class PDFPrintServiceFactory {
6385   static get supportsPrinting() {
6386     const canvas = document.createElement("canvas");
6387     return shadow(this, "supportsPrinting", "mozPrintCallback" in canvas);
6388   }
6389   static createPrintService(params) {
6390     return new FirefoxPrintService(params);
6391   }
6394 ;// ./web/pdf_rendering_queue.js
6397 const CLEANUP_TIMEOUT = 30000;
6398 class PDFRenderingQueue {
6399   constructor() {
6400     this.pdfViewer = null;
6401     this.pdfThumbnailViewer = null;
6402     this.onIdle = null;
6403     this.highestPriorityPage = null;
6404     this.idleTimeout = null;
6405     this.printing = false;
6406     this.isThumbnailViewEnabled = false;
6407   }
6408   setViewer(pdfViewer) {
6409     this.pdfViewer = pdfViewer;
6410   }
6411   setThumbnailViewer(pdfThumbnailViewer) {
6412     this.pdfThumbnailViewer = pdfThumbnailViewer;
6413   }
6414   isHighestPriority(view) {
6415     return this.highestPriorityPage === view.renderingId;
6416   }
6417   renderHighestPriority(currentlyVisiblePages) {
6418     if (this.idleTimeout) {
6419       clearTimeout(this.idleTimeout);
6420       this.idleTimeout = null;
6421     }
6422     if (this.pdfViewer.forceRendering(currentlyVisiblePages)) {
6423       return;
6424     }
6425     if (this.isThumbnailViewEnabled && this.pdfThumbnailViewer?.forceRendering()) {
6426       return;
6427     }
6428     if (this.printing) {
6429       return;
6430     }
6431     if (this.onIdle) {
6432       this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
6433     }
6434   }
6435   getHighestPriority(visible, views, scrolledDown, preRenderExtra = false) {
6436     const visibleViews = visible.views,
6437       numVisible = visibleViews.length;
6438     if (numVisible === 0) {
6439       return null;
6440     }
6441     for (let i = 0; i < numVisible; i++) {
6442       const view = visibleViews[i].view;
6443       if (!this.isViewFinished(view)) {
6444         return view;
6445       }
6446     }
6447     const firstId = visible.first.id,
6448       lastId = visible.last.id;
6449     if (lastId - firstId + 1 > numVisible) {
6450       const visibleIds = visible.ids;
6451       for (let i = 1, ii = lastId - firstId; i < ii; i++) {
6452         const holeId = scrolledDown ? firstId + i : lastId - i;
6453         if (visibleIds.has(holeId)) {
6454           continue;
6455         }
6456         const holeView = views[holeId - 1];
6457         if (!this.isViewFinished(holeView)) {
6458           return holeView;
6459         }
6460       }
6461     }
6462     let preRenderIndex = scrolledDown ? lastId : firstId - 2;
6463     let preRenderView = views[preRenderIndex];
6464     if (preRenderView && !this.isViewFinished(preRenderView)) {
6465       return preRenderView;
6466     }
6467     if (preRenderExtra) {
6468       preRenderIndex += scrolledDown ? 1 : -1;
6469       preRenderView = views[preRenderIndex];
6470       if (preRenderView && !this.isViewFinished(preRenderView)) {
6471         return preRenderView;
6472       }
6473     }
6474     return null;
6475   }
6476   isViewFinished(view) {
6477     return view.renderingState === RenderingStates.FINISHED;
6478   }
6479   renderView(view) {
6480     switch (view.renderingState) {
6481       case RenderingStates.FINISHED:
6482         return false;
6483       case RenderingStates.PAUSED:
6484         this.highestPriorityPage = view.renderingId;
6485         view.resume();
6486         break;
6487       case RenderingStates.RUNNING:
6488         this.highestPriorityPage = view.renderingId;
6489         break;
6490       case RenderingStates.INITIAL:
6491         this.highestPriorityPage = view.renderingId;
6492         view.draw().finally(() => {
6493           this.renderHighestPriority();
6494         }).catch(reason => {
6495           if (reason instanceof RenderingCancelledException) {
6496             return;
6497           }
6498           console.error("renderView:", reason);
6499         });
6500         break;
6501     }
6502     return true;
6503   }
6506 ;// ./web/pdf_scripting_manager.js
6509 class PDFScriptingManager {
6510   #closeCapability = null;
6511   #destroyCapability = null;
6512   #docProperties = null;
6513   #eventAbortController = null;
6514   #eventBus = null;
6515   #externalServices = null;
6516   #pdfDocument = null;
6517   #pdfViewer = null;
6518   #ready = false;
6519   #scripting = null;
6520   #willPrintCapability = null;
6521   constructor({
6522     eventBus,
6523     externalServices = null,
6524     docProperties = null
6525   }) {
6526     this.#eventBus = eventBus;
6527     this.#externalServices = externalServices;
6528     this.#docProperties = docProperties;
6529   }
6530   setViewer(pdfViewer) {
6531     this.#pdfViewer = pdfViewer;
6532   }
6533   async setDocument(pdfDocument) {
6534     if (this.#pdfDocument) {
6535       await this.#destroyScripting();
6536     }
6537     this.#pdfDocument = pdfDocument;
6538     if (!pdfDocument) {
6539       return;
6540     }
6541     const [objects, calculationOrder, docActions] = await Promise.all([pdfDocument.getFieldObjects(), pdfDocument.getCalculationOrderIds(), pdfDocument.getJSActions()]);
6542     if (!objects && !docActions) {
6543       await this.#destroyScripting();
6544       return;
6545     }
6546     if (pdfDocument !== this.#pdfDocument) {
6547       return;
6548     }
6549     try {
6550       this.#scripting = this.#initScripting();
6551     } catch (error) {
6552       console.error("setDocument:", error);
6553       await this.#destroyScripting();
6554       return;
6555     }
6556     const eventBus = this.#eventBus;
6557     this.#eventAbortController = new AbortController();
6558     const {
6559       signal
6560     } = this.#eventAbortController;
6561     eventBus._on("updatefromsandbox", event => {
6562       if (event?.source === window) {
6563         this.#updateFromSandbox(event.detail);
6564       }
6565     }, {
6566       signal
6567     });
6568     eventBus._on("dispatcheventinsandbox", event => {
6569       this.#scripting?.dispatchEventInSandbox(event.detail);
6570     }, {
6571       signal
6572     });
6573     eventBus._on("pagechanging", ({
6574       pageNumber,
6575       previous
6576     }) => {
6577       if (pageNumber === previous) {
6578         return;
6579       }
6580       this.#dispatchPageClose(previous);
6581       this.#dispatchPageOpen(pageNumber);
6582     }, {
6583       signal
6584     });
6585     eventBus._on("pagerendered", ({
6586       pageNumber
6587     }) => {
6588       if (!this._pageOpenPending.has(pageNumber)) {
6589         return;
6590       }
6591       if (pageNumber !== this.#pdfViewer.currentPageNumber) {
6592         return;
6593       }
6594       this.#dispatchPageOpen(pageNumber);
6595     }, {
6596       signal
6597     });
6598     eventBus._on("pagesdestroy", async () => {
6599       await this.#dispatchPageClose(this.#pdfViewer.currentPageNumber);
6600       await this.#scripting?.dispatchEventInSandbox({
6601         id: "doc",
6602         name: "WillClose"
6603       });
6604       this.#closeCapability?.resolve();
6605     }, {
6606       signal
6607     });
6608     try {
6609       const docProperties = await this.#docProperties(pdfDocument);
6610       if (pdfDocument !== this.#pdfDocument) {
6611         return;
6612       }
6613       await this.#scripting.createSandbox({
6614         objects,
6615         calculationOrder,
6616         appInfo: {
6617           platform: navigator.platform,
6618           language: navigator.language
6619         },
6620         docInfo: {
6621           ...docProperties,
6622           actions: docActions
6623         }
6624       });
6625       eventBus.dispatch("sandboxcreated", {
6626         source: this
6627       });
6628     } catch (error) {
6629       console.error("setDocument:", error);
6630       await this.#destroyScripting();
6631       return;
6632     }
6633     await this.#scripting?.dispatchEventInSandbox({
6634       id: "doc",
6635       name: "Open"
6636     });
6637     await this.#dispatchPageOpen(this.#pdfViewer.currentPageNumber, true);
6638     Promise.resolve().then(() => {
6639       if (pdfDocument === this.#pdfDocument) {
6640         this.#ready = true;
6641       }
6642     });
6643   }
6644   async dispatchWillSave() {
6645     return this.#scripting?.dispatchEventInSandbox({
6646       id: "doc",
6647       name: "WillSave"
6648     });
6649   }
6650   async dispatchDidSave() {
6651     return this.#scripting?.dispatchEventInSandbox({
6652       id: "doc",
6653       name: "DidSave"
6654     });
6655   }
6656   async dispatchWillPrint() {
6657     if (!this.#scripting) {
6658       return;
6659     }
6660     await this.#willPrintCapability?.promise;
6661     this.#willPrintCapability = Promise.withResolvers();
6662     try {
6663       await this.#scripting.dispatchEventInSandbox({
6664         id: "doc",
6665         name: "WillPrint"
6666       });
6667     } catch (ex) {
6668       this.#willPrintCapability.resolve();
6669       this.#willPrintCapability = null;
6670       throw ex;
6671     }
6672     await this.#willPrintCapability.promise;
6673   }
6674   async dispatchDidPrint() {
6675     return this.#scripting?.dispatchEventInSandbox({
6676       id: "doc",
6677       name: "DidPrint"
6678     });
6679   }
6680   get destroyPromise() {
6681     return this.#destroyCapability?.promise || null;
6682   }
6683   get ready() {
6684     return this.#ready;
6685   }
6686   get _pageOpenPending() {
6687     return shadow(this, "_pageOpenPending", new Set());
6688   }
6689   get _visitedPages() {
6690     return shadow(this, "_visitedPages", new Map());
6691   }
6692   async #updateFromSandbox(detail) {
6693     const pdfViewer = this.#pdfViewer;
6694     const isInPresentationMode = pdfViewer.isInPresentationMode || pdfViewer.isChangingPresentationMode;
6695     const {
6696       id,
6697       siblings,
6698       command,
6699       value
6700     } = detail;
6701     if (!id) {
6702       switch (command) {
6703         case "clear":
6704           console.clear();
6705           break;
6706         case "error":
6707           console.error(value);
6708           break;
6709         case "layout":
6710           if (!isInPresentationMode) {
6711             const modes = apiPageLayoutToViewerModes(value);
6712             pdfViewer.spreadMode = modes.spreadMode;
6713           }
6714           break;
6715         case "page-num":
6716           pdfViewer.currentPageNumber = value + 1;
6717           break;
6718         case "print":
6719           await pdfViewer.pagesPromise;
6720           this.#eventBus.dispatch("print", {
6721             source: this
6722           });
6723           break;
6724         case "println":
6725           console.log(value);
6726           break;
6727         case "zoom":
6728           if (!isInPresentationMode) {
6729             pdfViewer.currentScaleValue = value;
6730           }
6731           break;
6732         case "SaveAs":
6733           this.#eventBus.dispatch("download", {
6734             source: this
6735           });
6736           break;
6737         case "FirstPage":
6738           pdfViewer.currentPageNumber = 1;
6739           break;
6740         case "LastPage":
6741           pdfViewer.currentPageNumber = pdfViewer.pagesCount;
6742           break;
6743         case "NextPage":
6744           pdfViewer.nextPage();
6745           break;
6746         case "PrevPage":
6747           pdfViewer.previousPage();
6748           break;
6749         case "ZoomViewIn":
6750           if (!isInPresentationMode) {
6751             pdfViewer.increaseScale();
6752           }
6753           break;
6754         case "ZoomViewOut":
6755           if (!isInPresentationMode) {
6756             pdfViewer.decreaseScale();
6757           }
6758           break;
6759         case "WillPrintFinished":
6760           this.#willPrintCapability?.resolve();
6761           this.#willPrintCapability = null;
6762           break;
6763       }
6764       return;
6765     }
6766     if (isInPresentationMode && detail.focus) {
6767       return;
6768     }
6769     delete detail.id;
6770     delete detail.siblings;
6771     const ids = siblings ? [id, ...siblings] : [id];
6772     for (const elementId of ids) {
6773       const element = document.querySelector(`[data-element-id="${elementId}"]`);
6774       if (element) {
6775         element.dispatchEvent(new CustomEvent("updatefromsandbox", {
6776           detail
6777         }));
6778       } else {
6779         this.#pdfDocument?.annotationStorage.setValue(elementId, detail);
6780       }
6781     }
6782   }
6783   async #dispatchPageOpen(pageNumber, initialize = false) {
6784     const pdfDocument = this.#pdfDocument,
6785       visitedPages = this._visitedPages;
6786     if (initialize) {
6787       this.#closeCapability = Promise.withResolvers();
6788     }
6789     if (!this.#closeCapability) {
6790       return;
6791     }
6792     const pageView = this.#pdfViewer.getPageView(pageNumber - 1);
6793     if (pageView?.renderingState !== RenderingStates.FINISHED) {
6794       this._pageOpenPending.add(pageNumber);
6795       return;
6796     }
6797     this._pageOpenPending.delete(pageNumber);
6798     const actionsPromise = (async () => {
6799       const actions = await (!visitedPages.has(pageNumber) ? pageView.pdfPage?.getJSActions() : null);
6800       if (pdfDocument !== this.#pdfDocument) {
6801         return;
6802       }
6803       await this.#scripting?.dispatchEventInSandbox({
6804         id: "page",
6805         name: "PageOpen",
6806         pageNumber,
6807         actions
6808       });
6809     })();
6810     visitedPages.set(pageNumber, actionsPromise);
6811   }
6812   async #dispatchPageClose(pageNumber) {
6813     const pdfDocument = this.#pdfDocument,
6814       visitedPages = this._visitedPages;
6815     if (!this.#closeCapability) {
6816       return;
6817     }
6818     if (this._pageOpenPending.has(pageNumber)) {
6819       return;
6820     }
6821     const actionsPromise = visitedPages.get(pageNumber);
6822     if (!actionsPromise) {
6823       return;
6824     }
6825     visitedPages.set(pageNumber, null);
6826     await actionsPromise;
6827     if (pdfDocument !== this.#pdfDocument) {
6828       return;
6829     }
6830     await this.#scripting?.dispatchEventInSandbox({
6831       id: "page",
6832       name: "PageClose",
6833       pageNumber
6834     });
6835   }
6836   #initScripting() {
6837     this.#destroyCapability = Promise.withResolvers();
6838     if (this.#scripting) {
6839       throw new Error("#initScripting: Scripting already exists.");
6840     }
6841     return this.#externalServices.createScripting();
6842   }
6843   async #destroyScripting() {
6844     if (!this.#scripting) {
6845       this.#pdfDocument = null;
6846       this.#destroyCapability?.resolve();
6847       return;
6848     }
6849     if (this.#closeCapability) {
6850       await Promise.race([this.#closeCapability.promise, new Promise(resolve => {
6851         setTimeout(resolve, 1000);
6852       })]).catch(() => {});
6853       this.#closeCapability = null;
6854     }
6855     this.#pdfDocument = null;
6856     try {
6857       await this.#scripting.destroySandbox();
6858     } catch {}
6859     this.#willPrintCapability?.reject(new Error("Scripting destroyed."));
6860     this.#willPrintCapability = null;
6861     this.#eventAbortController?.abort();
6862     this.#eventAbortController = null;
6863     this._pageOpenPending.clear();
6864     this._visitedPages.clear();
6865     this.#scripting = null;
6866     this.#ready = false;
6867     this.#destroyCapability?.resolve();
6868   }
6871 ;// ./web/pdf_sidebar.js
6873 const SIDEBAR_WIDTH_VAR = "--sidebar-width";
6874 const SIDEBAR_MIN_WIDTH = 200;
6875 const SIDEBAR_RESIZING_CLASS = "sidebarResizing";
6876 const UI_NOTIFICATION_CLASS = "pdfSidebarNotification";
6877 class PDFSidebar {
6878   #isRTL = false;
6879   #mouseAC = null;
6880   #outerContainerWidth = null;
6881   #width = null;
6882   constructor({
6883     elements,
6884     eventBus,
6885     l10n
6886   }) {
6887     this.isOpen = false;
6888     this.active = SidebarView.THUMBS;
6889     this.isInitialViewSet = false;
6890     this.isInitialEventDispatched = false;
6891     this.onToggled = null;
6892     this.onUpdateThumbnails = null;
6893     this.outerContainer = elements.outerContainer;
6894     this.sidebarContainer = elements.sidebarContainer;
6895     this.toggleButton = elements.toggleButton;
6896     this.resizer = elements.resizer;
6897     this.thumbnailButton = elements.thumbnailButton;
6898     this.outlineButton = elements.outlineButton;
6899     this.attachmentsButton = elements.attachmentsButton;
6900     this.layersButton = elements.layersButton;
6901     this.thumbnailView = elements.thumbnailView;
6902     this.outlineView = elements.outlineView;
6903     this.attachmentsView = elements.attachmentsView;
6904     this.layersView = elements.layersView;
6905     this._currentOutlineItemButton = elements.currentOutlineItemButton;
6906     this.eventBus = eventBus;
6907     this.#isRTL = l10n.getDirection() === "rtl";
6908     this.#addEventListeners();
6909   }
6910   reset() {
6911     this.isInitialViewSet = false;
6912     this.isInitialEventDispatched = false;
6913     this.#hideUINotification(true);
6914     this.switchView(SidebarView.THUMBS);
6915     this.outlineButton.disabled = false;
6916     this.attachmentsButton.disabled = false;
6917     this.layersButton.disabled = false;
6918     this._currentOutlineItemButton.disabled = true;
6919   }
6920   get visibleView() {
6921     return this.isOpen ? this.active : SidebarView.NONE;
6922   }
6923   setInitialView(view = SidebarView.NONE) {
6924     if (this.isInitialViewSet) {
6925       return;
6926     }
6927     this.isInitialViewSet = true;
6928     if (view === SidebarView.NONE || view === SidebarView.UNKNOWN) {
6929       this.#dispatchEvent();
6930       return;
6931     }
6932     this.switchView(view, true);
6933     if (!this.isInitialEventDispatched) {
6934       this.#dispatchEvent();
6935     }
6936   }
6937   switchView(view, forceOpen = false) {
6938     const isViewChanged = view !== this.active;
6939     let forceRendering = false;
6940     switch (view) {
6941       case SidebarView.NONE:
6942         if (this.isOpen) {
6943           this.close();
6944         }
6945         return;
6946       case SidebarView.THUMBS:
6947         if (this.isOpen && isViewChanged) {
6948           forceRendering = true;
6949         }
6950         break;
6951       case SidebarView.OUTLINE:
6952         if (this.outlineButton.disabled) {
6953           return;
6954         }
6955         break;
6956       case SidebarView.ATTACHMENTS:
6957         if (this.attachmentsButton.disabled) {
6958           return;
6959         }
6960         break;
6961       case SidebarView.LAYERS:
6962         if (this.layersButton.disabled) {
6963           return;
6964         }
6965         break;
6966       default:
6967         console.error(`PDFSidebar.switchView: "${view}" is not a valid view.`);
6968         return;
6969     }
6970     this.active = view;
6971     toggleCheckedBtn(this.thumbnailButton, view === SidebarView.THUMBS, this.thumbnailView);
6972     toggleCheckedBtn(this.outlineButton, view === SidebarView.OUTLINE, this.outlineView);
6973     toggleCheckedBtn(this.attachmentsButton, view === SidebarView.ATTACHMENTS, this.attachmentsView);
6974     toggleCheckedBtn(this.layersButton, view === SidebarView.LAYERS, this.layersView);
6975     if (forceOpen && !this.isOpen) {
6976       this.open();
6977       return;
6978     }
6979     if (forceRendering) {
6980       this.onUpdateThumbnails();
6981       this.onToggled();
6982     }
6983     if (isViewChanged) {
6984       this.#dispatchEvent();
6985     }
6986   }
6987   open() {
6988     if (this.isOpen) {
6989       return;
6990     }
6991     this.isOpen = true;
6992     toggleExpandedBtn(this.toggleButton, true);
6993     this.outerContainer.classList.add("sidebarMoving", "sidebarOpen");
6994     if (this.active === SidebarView.THUMBS) {
6995       this.onUpdateThumbnails();
6996     }
6997     this.onToggled();
6998     this.#dispatchEvent();
6999     this.#hideUINotification();
7000   }
7001   close(evt = null) {
7002     if (!this.isOpen) {
7003       return;
7004     }
7005     this.isOpen = false;
7006     toggleExpandedBtn(this.toggleButton, false);
7007     this.outerContainer.classList.add("sidebarMoving");
7008     this.outerContainer.classList.remove("sidebarOpen");
7009     this.onToggled();
7010     this.#dispatchEvent();
7011     if (evt?.detail > 0) {
7012       this.toggleButton.blur();
7013     }
7014   }
7015   toggle(evt = null) {
7016     if (this.isOpen) {
7017       this.close(evt);
7018     } else {
7019       this.open();
7020     }
7021   }
7022   #dispatchEvent() {
7023     if (this.isInitialViewSet) {
7024       this.isInitialEventDispatched ||= true;
7025     }
7026     this.eventBus.dispatch("sidebarviewchanged", {
7027       source: this,
7028       view: this.visibleView
7029     });
7030   }
7031   #showUINotification() {
7032     this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-notification-button");
7033     if (!this.isOpen) {
7034       this.toggleButton.classList.add(UI_NOTIFICATION_CLASS);
7035     }
7036   }
7037   #hideUINotification(reset = false) {
7038     if (this.isOpen || reset) {
7039       this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS);
7040     }
7041     if (reset) {
7042       this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-button");
7043     }
7044   }
7045   #addEventListeners() {
7046     const {
7047       eventBus,
7048       outerContainer
7049     } = this;
7050     this.sidebarContainer.addEventListener("transitionend", evt => {
7051       if (evt.target === this.sidebarContainer) {
7052         outerContainer.classList.remove("sidebarMoving");
7053         eventBus.dispatch("resize", {
7054           source: this
7055         });
7056       }
7057     });
7058     this.toggleButton.addEventListener("click", evt => {
7059       this.toggle(evt);
7060     });
7061     this.thumbnailButton.addEventListener("click", () => {
7062       this.switchView(SidebarView.THUMBS);
7063     });
7064     this.outlineButton.addEventListener("click", () => {
7065       this.switchView(SidebarView.OUTLINE);
7066     });
7067     this.outlineButton.addEventListener("dblclick", () => {
7068       eventBus.dispatch("toggleoutlinetree", {
7069         source: this
7070       });
7071     });
7072     this.attachmentsButton.addEventListener("click", () => {
7073       this.switchView(SidebarView.ATTACHMENTS);
7074     });
7075     this.layersButton.addEventListener("click", () => {
7076       this.switchView(SidebarView.LAYERS);
7077     });
7078     this.layersButton.addEventListener("dblclick", () => {
7079       eventBus.dispatch("resetlayers", {
7080         source: this
7081       });
7082     });
7083     this._currentOutlineItemButton.addEventListener("click", () => {
7084       eventBus.dispatch("currentoutlineitem", {
7085         source: this
7086       });
7087     });
7088     const onTreeLoaded = (count, button, view) => {
7089       button.disabled = !count;
7090       if (count) {
7091         this.#showUINotification();
7092       } else if (this.active === view) {
7093         this.switchView(SidebarView.THUMBS);
7094       }
7095     };
7096     eventBus._on("outlineloaded", evt => {
7097       onTreeLoaded(evt.outlineCount, this.outlineButton, SidebarView.OUTLINE);
7098       evt.currentOutlineItemPromise.then(enabled => {
7099         if (!this.isInitialViewSet) {
7100           return;
7101         }
7102         this._currentOutlineItemButton.disabled = !enabled;
7103       });
7104     });
7105     eventBus._on("attachmentsloaded", evt => {
7106       onTreeLoaded(evt.attachmentsCount, this.attachmentsButton, SidebarView.ATTACHMENTS);
7107     });
7108     eventBus._on("layersloaded", evt => {
7109       onTreeLoaded(evt.layersCount, this.layersButton, SidebarView.LAYERS);
7110     });
7111     eventBus._on("presentationmodechanged", evt => {
7112       if (evt.state === PresentationModeState.NORMAL && this.visibleView === SidebarView.THUMBS) {
7113         this.onUpdateThumbnails();
7114       }
7115     });
7116     this.resizer.addEventListener("mousedown", evt => {
7117       if (evt.button !== 0) {
7118         return;
7119       }
7120       outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
7121       this.#mouseAC = new AbortController();
7122       const opts = {
7123         signal: this.#mouseAC.signal
7124       };
7125       window.addEventListener("mousemove", this.#mouseMove.bind(this), opts);
7126       window.addEventListener("mouseup", this.#mouseUp.bind(this), opts);
7127       window.addEventListener("blur", this.#mouseUp.bind(this), opts);
7128     });
7129     eventBus._on("resize", evt => {
7130       if (evt.source !== window) {
7131         return;
7132       }
7133       this.#outerContainerWidth = null;
7134       if (!this.#width) {
7135         return;
7136       }
7137       if (!this.isOpen) {
7138         this.#updateWidth(this.#width);
7139         return;
7140       }
7141       outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
7142       const updated = this.#updateWidth(this.#width);
7143       Promise.resolve().then(() => {
7144         outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);
7145         if (updated) {
7146           eventBus.dispatch("resize", {
7147             source: this
7148           });
7149         }
7150       });
7151     });
7152   }
7153   get outerContainerWidth() {
7154     return this.#outerContainerWidth ||= this.outerContainer.clientWidth;
7155   }
7156   #updateWidth(width = 0) {
7157     const maxWidth = Math.floor(this.outerContainerWidth / 2);
7158     if (width > maxWidth) {
7159       width = maxWidth;
7160     }
7161     if (width < SIDEBAR_MIN_WIDTH) {
7162       width = SIDEBAR_MIN_WIDTH;
7163     }
7164     if (width === this.#width) {
7165       return false;
7166     }
7167     this.#width = width;
7168     docStyle.setProperty(SIDEBAR_WIDTH_VAR, `${width}px`);
7169     return true;
7170   }
7171   #mouseMove(evt) {
7172     let width = evt.clientX;
7173     if (this.#isRTL) {
7174       width = this.outerContainerWidth - width;
7175     }
7176     this.#updateWidth(width);
7177   }
7178   #mouseUp(evt) {
7179     this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);
7180     this.eventBus.dispatch("resize", {
7181       source: this
7182     });
7183     this.#mouseAC?.abort();
7184     this.#mouseAC = null;
7185   }
7188 ;// ./web/pdf_thumbnail_view.js
7191 const DRAW_UPSCALE_FACTOR = 2;
7192 const MAX_NUM_SCALING_STEPS = 3;
7193 const THUMBNAIL_WIDTH = 98;
7194 class TempImageFactory {
7195   static #tempCanvas = null;
7196   static getCanvas(width, height) {
7197     const tempCanvas = this.#tempCanvas ||= document.createElement("canvas");
7198     tempCanvas.width = width;
7199     tempCanvas.height = height;
7200     const ctx = tempCanvas.getContext("2d", {
7201       alpha: false
7202     });
7203     ctx.save();
7204     ctx.fillStyle = "rgb(255, 255, 255)";
7205     ctx.fillRect(0, 0, width, height);
7206     ctx.restore();
7207     return [tempCanvas, tempCanvas.getContext("2d")];
7208   }
7209   static destroyCanvas() {
7210     const tempCanvas = this.#tempCanvas;
7211     if (tempCanvas) {
7212       tempCanvas.width = 0;
7213       tempCanvas.height = 0;
7214     }
7215     this.#tempCanvas = null;
7216   }
7218 class PDFThumbnailView {
7219   constructor({
7220     container,
7221     eventBus,
7222     id,
7223     defaultViewport,
7224     optionalContentConfigPromise,
7225     linkService,
7226     renderingQueue,
7227     pageColors,
7228     enableHWA
7229   }) {
7230     this.id = id;
7231     this.renderingId = "thumbnail" + id;
7232     this.pageLabel = null;
7233     this.pdfPage = null;
7234     this.rotation = 0;
7235     this.viewport = defaultViewport;
7236     this.pdfPageRotate = defaultViewport.rotation;
7237     this._optionalContentConfigPromise = optionalContentConfigPromise || null;
7238     this.pageColors = pageColors || null;
7239     this.enableHWA = enableHWA || false;
7240     this.eventBus = eventBus;
7241     this.linkService = linkService;
7242     this.renderingQueue = renderingQueue;
7243     this.renderTask = null;
7244     this.renderingState = RenderingStates.INITIAL;
7245     this.resume = null;
7246     const anchor = document.createElement("a");
7247     anchor.href = linkService.getAnchorUrl("#page=" + id);
7248     anchor.setAttribute("data-l10n-id", "pdfjs-thumb-page-title");
7249     anchor.setAttribute("data-l10n-args", this.#pageL10nArgs);
7250     anchor.onclick = function () {
7251       linkService.goToPage(id);
7252       return false;
7253     };
7254     this.anchor = anchor;
7255     const div = document.createElement("div");
7256     div.className = "thumbnail";
7257     div.setAttribute("data-page-number", this.id);
7258     this.div = div;
7259     this.#updateDims();
7260     const img = document.createElement("div");
7261     img.className = "thumbnailImage";
7262     this._placeholderImg = img;
7263     div.append(img);
7264     anchor.append(div);
7265     container.append(anchor);
7266   }
7267   #updateDims() {
7268     const {
7269       width,
7270       height
7271     } = this.viewport;
7272     const ratio = width / height;
7273     this.canvasWidth = THUMBNAIL_WIDTH;
7274     this.canvasHeight = this.canvasWidth / ratio | 0;
7275     this.scale = this.canvasWidth / width;
7276     const {
7277       style
7278     } = this.div;
7279     style.setProperty("--thumbnail-width", `${this.canvasWidth}px`);
7280     style.setProperty("--thumbnail-height", `${this.canvasHeight}px`);
7281   }
7282   setPdfPage(pdfPage) {
7283     this.pdfPage = pdfPage;
7284     this.pdfPageRotate = pdfPage.rotate;
7285     const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
7286     this.viewport = pdfPage.getViewport({
7287       scale: 1,
7288       rotation: totalRotation
7289     });
7290     this.reset();
7291   }
7292   reset() {
7293     this.cancelRendering();
7294     this.renderingState = RenderingStates.INITIAL;
7295     this.div.removeAttribute("data-loaded");
7296     this.image?.replaceWith(this._placeholderImg);
7297     this.#updateDims();
7298     if (this.image) {
7299       this.image.removeAttribute("src");
7300       delete this.image;
7301     }
7302   }
7303   update({
7304     rotation = null
7305   }) {
7306     if (typeof rotation === "number") {
7307       this.rotation = rotation;
7308     }
7309     const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
7310     this.viewport = this.viewport.clone({
7311       scale: 1,
7312       rotation: totalRotation
7313     });
7314     this.reset();
7315   }
7316   cancelRendering() {
7317     if (this.renderTask) {
7318       this.renderTask.cancel();
7319       this.renderTask = null;
7320     }
7321     this.resume = null;
7322   }
7323   #getPageDrawContext(upscaleFactor = 1, enableHWA = this.enableHWA) {
7324     const canvas = document.createElement("canvas");
7325     const ctx = canvas.getContext("2d", {
7326       alpha: false,
7327       willReadFrequently: !enableHWA
7328     });
7329     const outputScale = new OutputScale();
7330     canvas.width = upscaleFactor * this.canvasWidth * outputScale.sx | 0;
7331     canvas.height = upscaleFactor * this.canvasHeight * outputScale.sy | 0;
7332     const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;
7333     return {
7334       ctx,
7335       canvas,
7336       transform
7337     };
7338   }
7339   #convertCanvasToImage(canvas) {
7340     if (this.renderingState !== RenderingStates.FINISHED) {
7341       throw new Error("#convertCanvasToImage: Rendering has not finished.");
7342     }
7343     const reducedCanvas = this.#reduceImage(canvas);
7344     const image = document.createElement("img");
7345     image.className = "thumbnailImage";
7346     image.setAttribute("data-l10n-id", "pdfjs-thumb-page-canvas");
7347     image.setAttribute("data-l10n-args", this.#pageL10nArgs);
7348     image.src = reducedCanvas.toDataURL();
7349     this.image = image;
7350     this.div.setAttribute("data-loaded", true);
7351     this._placeholderImg.replaceWith(image);
7352     reducedCanvas.width = 0;
7353     reducedCanvas.height = 0;
7354   }
7355   async #finishRenderTask(renderTask, canvas, error = null) {
7356     if (renderTask === this.renderTask) {
7357       this.renderTask = null;
7358     }
7359     if (error instanceof RenderingCancelledException) {
7360       return;
7361     }
7362     this.renderingState = RenderingStates.FINISHED;
7363     this.#convertCanvasToImage(canvas);
7364     if (error) {
7365       throw error;
7366     }
7367   }
7368   async draw() {
7369     if (this.renderingState !== RenderingStates.INITIAL) {
7370       console.error("Must be in new state before drawing");
7371       return undefined;
7372     }
7373     const {
7374       pdfPage
7375     } = this;
7376     if (!pdfPage) {
7377       this.renderingState = RenderingStates.FINISHED;
7378       throw new Error("pdfPage is not loaded");
7379     }
7380     this.renderingState = RenderingStates.RUNNING;
7381     const {
7382       ctx,
7383       canvas,
7384       transform
7385     } = this.#getPageDrawContext(DRAW_UPSCALE_FACTOR);
7386     const drawViewport = this.viewport.clone({
7387       scale: DRAW_UPSCALE_FACTOR * this.scale
7388     });
7389     const renderContinueCallback = cont => {
7390       if (!this.renderingQueue.isHighestPriority(this)) {
7391         this.renderingState = RenderingStates.PAUSED;
7392         this.resume = () => {
7393           this.renderingState = RenderingStates.RUNNING;
7394           cont();
7395         };
7396         return;
7397       }
7398       cont();
7399     };
7400     const renderContext = {
7401       canvasContext: ctx,
7402       transform,
7403       viewport: drawViewport,
7404       optionalContentConfigPromise: this._optionalContentConfigPromise,
7405       pageColors: this.pageColors
7406     };
7407     const renderTask = this.renderTask = pdfPage.render(renderContext);
7408     renderTask.onContinue = renderContinueCallback;
7409     const resultPromise = renderTask.promise.then(() => this.#finishRenderTask(renderTask, canvas), error => this.#finishRenderTask(renderTask, canvas, error));
7410     resultPromise.finally(() => {
7411       canvas.width = 0;
7412       canvas.height = 0;
7413       this.eventBus.dispatch("thumbnailrendered", {
7414         source: this,
7415         pageNumber: this.id,
7416         pdfPage: this.pdfPage
7417       });
7418     });
7419     return resultPromise;
7420   }
7421   setImage(pageView) {
7422     if (this.renderingState !== RenderingStates.INITIAL) {
7423       return;
7424     }
7425     const {
7426       thumbnailCanvas: canvas,
7427       pdfPage,
7428       scale
7429     } = pageView;
7430     if (!canvas) {
7431       return;
7432     }
7433     if (!this.pdfPage) {
7434       this.setPdfPage(pdfPage);
7435     }
7436     if (scale < this.scale) {
7437       return;
7438     }
7439     this.renderingState = RenderingStates.FINISHED;
7440     this.#convertCanvasToImage(canvas);
7441   }
7442   #reduceImage(img) {
7443     const {
7444       ctx,
7445       canvas
7446     } = this.#getPageDrawContext(1, true);
7447     if (img.width <= 2 * canvas.width) {
7448       ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
7449       return canvas;
7450     }
7451     let reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS;
7452     let reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS;
7453     const [reducedImage, reducedImageCtx] = TempImageFactory.getCanvas(reducedWidth, reducedHeight);
7454     while (reducedWidth > img.width || reducedHeight > img.height) {
7455       reducedWidth >>= 1;
7456       reducedHeight >>= 1;
7457     }
7458     reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight);
7459     while (reducedWidth > 2 * canvas.width) {
7460       reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1);
7461       reducedWidth >>= 1;
7462       reducedHeight >>= 1;
7463     }
7464     ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height);
7465     return canvas;
7466   }
7467   get #pageL10nArgs() {
7468     return JSON.stringify({
7469       page: this.pageLabel ?? this.id
7470     });
7471   }
7472   setPageLabel(label) {
7473     this.pageLabel = typeof label === "string" ? label : null;
7474     this.anchor.setAttribute("data-l10n-args", this.#pageL10nArgs);
7475     if (this.renderingState !== RenderingStates.FINISHED) {
7476       return;
7477     }
7478     this.image?.setAttribute("data-l10n-args", this.#pageL10nArgs);
7479   }
7482 ;// ./web/pdf_thumbnail_viewer.js
7485 const THUMBNAIL_SCROLL_MARGIN = -19;
7486 const THUMBNAIL_SELECTED_CLASS = "selected";
7487 class PDFThumbnailViewer {
7488   constructor({
7489     container,
7490     eventBus,
7491     linkService,
7492     renderingQueue,
7493     pageColors,
7494     abortSignal,
7495     enableHWA
7496   }) {
7497     this.container = container;
7498     this.eventBus = eventBus;
7499     this.linkService = linkService;
7500     this.renderingQueue = renderingQueue;
7501     this.pageColors = pageColors || null;
7502     this.enableHWA = enableHWA || false;
7503     this.scroll = watchScroll(this.container, this.#scrollUpdated.bind(this), abortSignal);
7504     this.#resetView();
7505   }
7506   #scrollUpdated() {
7507     this.renderingQueue.renderHighestPriority();
7508   }
7509   getThumbnail(index) {
7510     return this._thumbnails[index];
7511   }
7512   #getVisibleThumbs() {
7513     return getVisibleElements({
7514       scrollEl: this.container,
7515       views: this._thumbnails
7516     });
7517   }
7518   scrollThumbnailIntoView(pageNumber) {
7519     if (!this.pdfDocument) {
7520       return;
7521     }
7522     const thumbnailView = this._thumbnails[pageNumber - 1];
7523     if (!thumbnailView) {
7524       console.error('scrollThumbnailIntoView: Invalid "pageNumber" parameter.');
7525       return;
7526     }
7527     if (pageNumber !== this._currentPageNumber) {
7528       const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1];
7529       prevThumbnailView.div.classList.remove(THUMBNAIL_SELECTED_CLASS);
7530       thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS);
7531     }
7532     const {
7533       first,
7534       last,
7535       views
7536     } = this.#getVisibleThumbs();
7537     if (views.length > 0) {
7538       let shouldScroll = false;
7539       if (pageNumber <= first.id || pageNumber >= last.id) {
7540         shouldScroll = true;
7541       } else {
7542         for (const {
7543           id,
7544           percent
7545         } of views) {
7546           if (id !== pageNumber) {
7547             continue;
7548           }
7549           shouldScroll = percent < 100;
7550           break;
7551         }
7552       }
7553       if (shouldScroll) {
7554         scrollIntoView(thumbnailView.div, {
7555           top: THUMBNAIL_SCROLL_MARGIN
7556         });
7557       }
7558     }
7559     this._currentPageNumber = pageNumber;
7560   }
7561   get pagesRotation() {
7562     return this._pagesRotation;
7563   }
7564   set pagesRotation(rotation) {
7565     if (!isValidRotation(rotation)) {
7566       throw new Error("Invalid thumbnails rotation angle.");
7567     }
7568     if (!this.pdfDocument) {
7569       return;
7570     }
7571     if (this._pagesRotation === rotation) {
7572       return;
7573     }
7574     this._pagesRotation = rotation;
7575     const updateArgs = {
7576       rotation
7577     };
7578     for (const thumbnail of this._thumbnails) {
7579       thumbnail.update(updateArgs);
7580     }
7581   }
7582   cleanup() {
7583     for (const thumbnail of this._thumbnails) {
7584       if (thumbnail.renderingState !== RenderingStates.FINISHED) {
7585         thumbnail.reset();
7586       }
7587     }
7588     TempImageFactory.destroyCanvas();
7589   }
7590   #resetView() {
7591     this._thumbnails = [];
7592     this._currentPageNumber = 1;
7593     this._pageLabels = null;
7594     this._pagesRotation = 0;
7595     this.container.textContent = "";
7596   }
7597   setDocument(pdfDocument) {
7598     if (this.pdfDocument) {
7599       this.#cancelRendering();
7600       this.#resetView();
7601     }
7602     this.pdfDocument = pdfDocument;
7603     if (!pdfDocument) {
7604       return;
7605     }
7606     const firstPagePromise = pdfDocument.getPage(1);
7607     const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
7608       intent: "display"
7609     });
7610     firstPagePromise.then(firstPdfPage => {
7611       const pagesCount = pdfDocument.numPages;
7612       const viewport = firstPdfPage.getViewport({
7613         scale: 1
7614       });
7615       for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
7616         const thumbnail = new PDFThumbnailView({
7617           container: this.container,
7618           eventBus: this.eventBus,
7619           id: pageNum,
7620           defaultViewport: viewport.clone(),
7621           optionalContentConfigPromise,
7622           linkService: this.linkService,
7623           renderingQueue: this.renderingQueue,
7624           pageColors: this.pageColors,
7625           enableHWA: this.enableHWA
7626         });
7627         this._thumbnails.push(thumbnail);
7628       }
7629       this._thumbnails[0]?.setPdfPage(firstPdfPage);
7630       const thumbnailView = this._thumbnails[this._currentPageNumber - 1];
7631       thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS);
7632     }).catch(reason => {
7633       console.error("Unable to initialize thumbnail viewer", reason);
7634     });
7635   }
7636   #cancelRendering() {
7637     for (const thumbnail of this._thumbnails) {
7638       thumbnail.cancelRendering();
7639     }
7640   }
7641   setPageLabels(labels) {
7642     if (!this.pdfDocument) {
7643       return;
7644     }
7645     if (!labels) {
7646       this._pageLabels = null;
7647     } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {
7648       this._pageLabels = null;
7649       console.error("PDFThumbnailViewer_setPageLabels: Invalid page labels.");
7650     } else {
7651       this._pageLabels = labels;
7652     }
7653     for (let i = 0, ii = this._thumbnails.length; i < ii; i++) {
7654       this._thumbnails[i].setPageLabel(this._pageLabels?.[i] ?? null);
7655     }
7656   }
7657   async #ensurePdfPageLoaded(thumbView) {
7658     if (thumbView.pdfPage) {
7659       return thumbView.pdfPage;
7660     }
7661     try {
7662       const pdfPage = await this.pdfDocument.getPage(thumbView.id);
7663       if (!thumbView.pdfPage) {
7664         thumbView.setPdfPage(pdfPage);
7665       }
7666       return pdfPage;
7667     } catch (reason) {
7668       console.error("Unable to get page for thumb view", reason);
7669       return null;
7670     }
7671   }
7672   #getScrollAhead(visible) {
7673     if (visible.first?.id === 1) {
7674       return true;
7675     } else if (visible.last?.id === this._thumbnails.length) {
7676       return false;
7677     }
7678     return this.scroll.down;
7679   }
7680   forceRendering() {
7681     const visibleThumbs = this.#getVisibleThumbs();
7682     const scrollAhead = this.#getScrollAhead(visibleThumbs);
7683     const thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, this._thumbnails, scrollAhead);
7684     if (thumbView) {
7685       this.#ensurePdfPageLoaded(thumbView).then(() => {
7686         this.renderingQueue.renderView(thumbView);
7687       });
7688       return true;
7689     }
7690     return false;
7691   }
7694 ;// ./web/annotation_editor_layer_builder.js
7697 class AnnotationEditorLayerBuilder {
7698   #annotationLayer = null;
7699   #drawLayer = null;
7700   #onAppend = null;
7701   #structTreeLayer = null;
7702   #textLayer = null;
7703   #uiManager;
7704   constructor(options) {
7705     this.pdfPage = options.pdfPage;
7706     this.accessibilityManager = options.accessibilityManager;
7707     this.l10n = options.l10n;
7708     this.annotationEditorLayer = null;
7709     this.div = null;
7710     this._cancelled = false;
7711     this.#uiManager = options.uiManager;
7712     this.#annotationLayer = options.annotationLayer || null;
7713     this.#textLayer = options.textLayer || null;
7714     this.#drawLayer = options.drawLayer || null;
7715     this.#onAppend = options.onAppend || null;
7716     this.#structTreeLayer = options.structTreeLayer || null;
7717   }
7718   async render({
7719     viewport,
7720     intent = "display"
7721   }) {
7722     if (intent !== "display") {
7723       return;
7724     }
7725     if (this._cancelled) {
7726       return;
7727     }
7728     const clonedViewport = viewport.clone({
7729       dontFlip: true
7730     });
7731     if (this.div) {
7732       this.annotationEditorLayer.update({
7733         viewport: clonedViewport
7734       });
7735       this.show();
7736       return;
7737     }
7738     const div = this.div = document.createElement("div");
7739     div.className = "annotationEditorLayer";
7740     div.hidden = true;
7741     div.dir = this.#uiManager.direction;
7742     this.#onAppend?.(div);
7743     this.annotationEditorLayer = new AnnotationEditorLayer({
7744       uiManager: this.#uiManager,
7745       div,
7746       structTreeLayer: this.#structTreeLayer,
7747       accessibilityManager: this.accessibilityManager,
7748       pageIndex: this.pdfPage.pageNumber - 1,
7749       l10n: this.l10n,
7750       viewport: clonedViewport,
7751       annotationLayer: this.#annotationLayer,
7752       textLayer: this.#textLayer,
7753       drawLayer: this.#drawLayer
7754     });
7755     const parameters = {
7756       viewport: clonedViewport,
7757       div,
7758       annotations: null,
7759       intent
7760     };
7761     this.annotationEditorLayer.render(parameters);
7762     this.show();
7763   }
7764   cancel() {
7765     this._cancelled = true;
7766     if (!this.div) {
7767       return;
7768     }
7769     this.annotationEditorLayer.destroy();
7770   }
7771   hide() {
7772     if (!this.div) {
7773       return;
7774     }
7775     this.annotationEditorLayer.pause(true);
7776     this.div.hidden = true;
7777   }
7778   show() {
7779     if (!this.div || this.annotationEditorLayer.isInvisible) {
7780       return;
7781     }
7782     this.div.hidden = false;
7783     this.annotationEditorLayer.pause(false);
7784   }
7787 ;// ./web/annotation_layer_builder.js
7790 class AnnotationLayerBuilder {
7791   #onAppend = null;
7792   #eventAbortController = null;
7793   constructor({
7794     pdfPage,
7795     linkService,
7796     downloadManager,
7797     annotationStorage = null,
7798     imageResourcesPath = "",
7799     renderForms = true,
7800     enableScripting = false,
7801     hasJSActionsPromise = null,
7802     fieldObjectsPromise = null,
7803     annotationCanvasMap = null,
7804     accessibilityManager = null,
7805     annotationEditorUIManager = null,
7806     onAppend = null
7807   }) {
7808     this.pdfPage = pdfPage;
7809     this.linkService = linkService;
7810     this.downloadManager = downloadManager;
7811     this.imageResourcesPath = imageResourcesPath;
7812     this.renderForms = renderForms;
7813     this.annotationStorage = annotationStorage;
7814     this.enableScripting = enableScripting;
7815     this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
7816     this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
7817     this._annotationCanvasMap = annotationCanvasMap;
7818     this._accessibilityManager = accessibilityManager;
7819     this._annotationEditorUIManager = annotationEditorUIManager;
7820     this.#onAppend = onAppend;
7821     this.annotationLayer = null;
7822     this.div = null;
7823     this._cancelled = false;
7824     this._eventBus = linkService.eventBus;
7825   }
7826   async render({
7827     viewport,
7828     intent = "display",
7829     structTreeLayer = null
7830   }) {
7831     if (this.div) {
7832       if (this._cancelled || !this.annotationLayer) {
7833         return;
7834       }
7835       this.annotationLayer.update({
7836         viewport: viewport.clone({
7837           dontFlip: true
7838         })
7839       });
7840       return;
7841     }
7842     const [annotations, hasJSActions, fieldObjects] = await Promise.all([this.pdfPage.getAnnotations({
7843       intent
7844     }), this._hasJSActionsPromise, this._fieldObjectsPromise]);
7845     if (this._cancelled) {
7846       return;
7847     }
7848     const div = this.div = document.createElement("div");
7849     div.className = "annotationLayer";
7850     this.#onAppend?.(div);
7851     if (annotations.length === 0) {
7852       this.hide();
7853       return;
7854     }
7855     this.annotationLayer = new AnnotationLayer({
7856       div,
7857       accessibilityManager: this._accessibilityManager,
7858       annotationCanvasMap: this._annotationCanvasMap,
7859       annotationEditorUIManager: this._annotationEditorUIManager,
7860       page: this.pdfPage,
7861       viewport: viewport.clone({
7862         dontFlip: true
7863       }),
7864       structTreeLayer
7865     });
7866     await this.annotationLayer.render({
7867       annotations,
7868       imageResourcesPath: this.imageResourcesPath,
7869       renderForms: this.renderForms,
7870       linkService: this.linkService,
7871       downloadManager: this.downloadManager,
7872       annotationStorage: this.annotationStorage,
7873       enableScripting: this.enableScripting,
7874       hasJSActions,
7875       fieldObjects
7876     });
7877     if (this.linkService.isInPresentationMode) {
7878       this.#updatePresentationModeState(PresentationModeState.FULLSCREEN);
7879     }
7880     if (!this.#eventAbortController) {
7881       this.#eventAbortController = new AbortController();
7882       this._eventBus?._on("presentationmodechanged", evt => {
7883         this.#updatePresentationModeState(evt.state);
7884       }, {
7885         signal: this.#eventAbortController.signal
7886       });
7887     }
7888   }
7889   cancel() {
7890     this._cancelled = true;
7891     this.#eventAbortController?.abort();
7892     this.#eventAbortController = null;
7893   }
7894   hide() {
7895     if (!this.div) {
7896       return;
7897     }
7898     this.div.hidden = true;
7899   }
7900   hasEditableAnnotations() {
7901     return !!this.annotationLayer?.hasEditableAnnotations();
7902   }
7903   #updatePresentationModeState(state) {
7904     if (!this.div) {
7905       return;
7906     }
7907     let disableFormElements = false;
7908     switch (state) {
7909       case PresentationModeState.FULLSCREEN:
7910         disableFormElements = true;
7911         break;
7912       case PresentationModeState.NORMAL:
7913         break;
7914       default:
7915         return;
7916     }
7917     for (const section of this.div.childNodes) {
7918       if (section.hasAttribute("data-internal-link")) {
7919         continue;
7920       }
7921       section.inert = disableFormElements;
7922     }
7923   }
7926 ;// ./web/draw_layer_builder.js
7928 class DrawLayerBuilder {
7929   #drawLayer = null;
7930   constructor(options) {
7931     this.pageIndex = options.pageIndex;
7932   }
7933   async render({
7934     intent = "display"
7935   }) {
7936     if (intent !== "display" || this.#drawLayer || this._cancelled) {
7937       return;
7938     }
7939     this.#drawLayer = new DrawLayer({
7940       pageIndex: this.pageIndex
7941     });
7942   }
7943   cancel() {
7944     this._cancelled = true;
7945     if (!this.#drawLayer) {
7946       return;
7947     }
7948     this.#drawLayer.destroy();
7949     this.#drawLayer = null;
7950   }
7951   setParent(parent) {
7952     this.#drawLayer?.setParent(parent);
7953   }
7954   getDrawLayer() {
7955     return this.#drawLayer;
7956   }
7959 ;// ./web/struct_tree_layer_builder.js
7961 const PDF_ROLE_TO_HTML_ROLE = {
7962   Document: null,
7963   DocumentFragment: null,
7964   Part: "group",
7965   Sect: "group",
7966   Div: "group",
7967   Aside: "note",
7968   NonStruct: "none",
7969   P: null,
7970   H: "heading",
7971   Title: null,
7972   FENote: "note",
7973   Sub: "group",
7974   Lbl: null,
7975   Span: null,
7976   Em: null,
7977   Strong: null,
7978   Link: "link",
7979   Annot: "note",
7980   Form: "form",
7981   Ruby: null,
7982   RB: null,
7983   RT: null,
7984   RP: null,
7985   Warichu: null,
7986   WT: null,
7987   WP: null,
7988   L: "list",
7989   LI: "listitem",
7990   LBody: null,
7991   Table: "table",
7992   TR: "row",
7993   TH: "columnheader",
7994   TD: "cell",
7995   THead: "columnheader",
7996   TBody: null,
7997   TFoot: null,
7998   Caption: null,
7999   Figure: "figure",
8000   Formula: null,
8001   Artifact: null
8003 const HEADING_PATTERN = /^H(\d+)$/;
8004 class StructTreeLayerBuilder {
8005   #promise;
8006   #treeDom = null;
8007   #treePromise;
8008   #elementAttributes = new Map();
8009   #rawDims;
8010   #elementsToAddToTextLayer = null;
8011   constructor(pdfPage, rawDims) {
8012     this.#promise = pdfPage.getStructTree();
8013     this.#rawDims = rawDims;
8014   }
8015   async render() {
8016     if (this.#treePromise) {
8017       return this.#treePromise;
8018     }
8019     const {
8020       promise,
8021       resolve,
8022       reject
8023     } = Promise.withResolvers();
8024     this.#treePromise = promise;
8025     try {
8026       this.#treeDom = this.#walk(await this.#promise);
8027     } catch (ex) {
8028       reject(ex);
8029     }
8030     this.#promise = null;
8031     this.#treeDom?.classList.add("structTree");
8032     resolve(this.#treeDom);
8033     return promise;
8034   }
8035   async getAriaAttributes(annotationId) {
8036     try {
8037       await this.render();
8038       return this.#elementAttributes.get(annotationId);
8039     } catch {}
8040     return null;
8041   }
8042   hide() {
8043     if (this.#treeDom && !this.#treeDom.hidden) {
8044       this.#treeDom.hidden = true;
8045     }
8046   }
8047   show() {
8048     if (this.#treeDom?.hidden) {
8049       this.#treeDom.hidden = false;
8050     }
8051   }
8052   #setAttributes(structElement, htmlElement) {
8053     const {
8054       alt,
8055       id,
8056       lang
8057     } = structElement;
8058     if (alt !== undefined) {
8059       let added = false;
8060       const label = removeNullCharacters(alt);
8061       for (const child of structElement.children) {
8062         if (child.type === "annotation") {
8063           let attrs = this.#elementAttributes.get(child.id);
8064           if (!attrs) {
8065             attrs = new Map();
8066             this.#elementAttributes.set(child.id, attrs);
8067           }
8068           attrs.set("aria-label", label);
8069           added = true;
8070         }
8071       }
8072       if (!added) {
8073         htmlElement.setAttribute("aria-label", label);
8074       }
8075     }
8076     if (id !== undefined) {
8077       htmlElement.setAttribute("aria-owns", id);
8078     }
8079     if (lang !== undefined) {
8080       htmlElement.setAttribute("lang", removeNullCharacters(lang, true));
8081     }
8082   }
8083   #addImageInTextLayer(node, element) {
8084     const {
8085       alt,
8086       bbox,
8087       children
8088     } = node;
8089     const child = children?.[0];
8090     if (!this.#rawDims || !alt || !bbox || child?.type !== "content") {
8091       return false;
8092     }
8093     const {
8094       id
8095     } = child;
8096     if (!id) {
8097       return false;
8098     }
8099     element.setAttribute("aria-owns", id);
8100     const img = document.createElement("span");
8101     (this.#elementsToAddToTextLayer ||= new Map()).set(id, img);
8102     img.setAttribute("role", "img");
8103     img.setAttribute("aria-label", removeNullCharacters(alt));
8104     const {
8105       pageHeight,
8106       pageX,
8107       pageY
8108     } = this.#rawDims;
8109     const calc = "calc(var(--scale-factor)*";
8110     const {
8111       style
8112     } = img;
8113     style.width = `${calc}${bbox[2] - bbox[0]}px)`;
8114     style.height = `${calc}${bbox[3] - bbox[1]}px)`;
8115     style.left = `${calc}${bbox[0] - pageX}px)`;
8116     style.top = `${calc}${pageHeight - bbox[3] + pageY}px)`;
8117     return true;
8118   }
8119   addElementsToTextLayer() {
8120     if (!this.#elementsToAddToTextLayer) {
8121       return;
8122     }
8123     for (const [id, img] of this.#elementsToAddToTextLayer) {
8124       document.getElementById(id)?.append(img);
8125     }
8126     this.#elementsToAddToTextLayer.clear();
8127     this.#elementsToAddToTextLayer = null;
8128   }
8129   #walk(node) {
8130     if (!node) {
8131       return null;
8132     }
8133     const element = document.createElement("span");
8134     if ("role" in node) {
8135       const {
8136         role
8137       } = node;
8138       const match = role.match(HEADING_PATTERN);
8139       if (match) {
8140         element.setAttribute("role", "heading");
8141         element.setAttribute("aria-level", match[1]);
8142       } else if (PDF_ROLE_TO_HTML_ROLE[role]) {
8143         element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]);
8144       }
8145       if (role === "Figure" && this.#addImageInTextLayer(node, element)) {
8146         return element;
8147       }
8148     }
8149     this.#setAttributes(node, element);
8150     if (node.children) {
8151       if (node.children.length === 1 && "id" in node.children[0]) {
8152         this.#setAttributes(node.children[0], element);
8153       } else {
8154         for (const kid of node.children) {
8155           element.append(this.#walk(kid));
8156         }
8157       }
8158     }
8159     return element;
8160   }
8163 ;// ./web/text_accessibility.js
8165 class TextAccessibilityManager {
8166   #enabled = false;
8167   #textChildren = null;
8168   #textNodes = new Map();
8169   #waitingElements = new Map();
8170   setTextMapping(textDivs) {
8171     this.#textChildren = textDivs;
8172   }
8173   static #compareElementPositions(e1, e2) {
8174     const rect1 = e1.getBoundingClientRect();
8175     const rect2 = e2.getBoundingClientRect();
8176     if (rect1.width === 0 && rect1.height === 0) {
8177       return +1;
8178     }
8179     if (rect2.width === 0 && rect2.height === 0) {
8180       return -1;
8181     }
8182     const top1 = rect1.y;
8183     const bot1 = rect1.y + rect1.height;
8184     const mid1 = rect1.y + rect1.height / 2;
8185     const top2 = rect2.y;
8186     const bot2 = rect2.y + rect2.height;
8187     const mid2 = rect2.y + rect2.height / 2;
8188     if (mid1 <= top2 && mid2 >= bot1) {
8189       return -1;
8190     }
8191     if (mid2 <= top1 && mid1 >= bot2) {
8192       return +1;
8193     }
8194     const centerX1 = rect1.x + rect1.width / 2;
8195     const centerX2 = rect2.x + rect2.width / 2;
8196     return centerX1 - centerX2;
8197   }
8198   enable() {
8199     if (this.#enabled) {
8200       throw new Error("TextAccessibilityManager is already enabled.");
8201     }
8202     if (!this.#textChildren) {
8203       throw new Error("Text divs and strings have not been set.");
8204     }
8205     this.#enabled = true;
8206     this.#textChildren = this.#textChildren.slice();
8207     this.#textChildren.sort(TextAccessibilityManager.#compareElementPositions);
8208     if (this.#textNodes.size > 0) {
8209       const textChildren = this.#textChildren;
8210       for (const [id, nodeIndex] of this.#textNodes) {
8211         const element = document.getElementById(id);
8212         if (!element) {
8213           this.#textNodes.delete(id);
8214           continue;
8215         }
8216         this.#addIdToAriaOwns(id, textChildren[nodeIndex]);
8217       }
8218     }
8219     for (const [element, isRemovable] of this.#waitingElements) {
8220       this.addPointerInTextLayer(element, isRemovable);
8221     }
8222     this.#waitingElements.clear();
8223   }
8224   disable() {
8225     if (!this.#enabled) {
8226       return;
8227     }
8228     this.#waitingElements.clear();
8229     this.#textChildren = null;
8230     this.#enabled = false;
8231   }
8232   removePointerInTextLayer(element) {
8233     if (!this.#enabled) {
8234       this.#waitingElements.delete(element);
8235       return;
8236     }
8237     const children = this.#textChildren;
8238     if (!children || children.length === 0) {
8239       return;
8240     }
8241     const {
8242       id
8243     } = element;
8244     const nodeIndex = this.#textNodes.get(id);
8245     if (nodeIndex === undefined) {
8246       return;
8247     }
8248     const node = children[nodeIndex];
8249     this.#textNodes.delete(id);
8250     let owns = node.getAttribute("aria-owns");
8251     if (owns?.includes(id)) {
8252       owns = owns.split(" ").filter(x => x !== id).join(" ");
8253       if (owns) {
8254         node.setAttribute("aria-owns", owns);
8255       } else {
8256         node.removeAttribute("aria-owns");
8257         node.setAttribute("role", "presentation");
8258       }
8259     }
8260   }
8261   #addIdToAriaOwns(id, node) {
8262     const owns = node.getAttribute("aria-owns");
8263     if (!owns?.includes(id)) {
8264       node.setAttribute("aria-owns", owns ? `${owns} ${id}` : id);
8265     }
8266     node.removeAttribute("role");
8267   }
8268   addPointerInTextLayer(element, isRemovable) {
8269     const {
8270       id
8271     } = element;
8272     if (!id) {
8273       return null;
8274     }
8275     if (!this.#enabled) {
8276       this.#waitingElements.set(element, isRemovable);
8277       return null;
8278     }
8279     if (isRemovable) {
8280       this.removePointerInTextLayer(element);
8281     }
8282     const children = this.#textChildren;
8283     if (!children || children.length === 0) {
8284       return null;
8285     }
8286     const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0);
8287     const nodeIndex = Math.max(0, index - 1);
8288     const child = children[nodeIndex];
8289     this.#addIdToAriaOwns(id, child);
8290     this.#textNodes.set(id, nodeIndex);
8291     const parent = child.parentNode;
8292     return parent?.classList.contains("markedContent") ? parent.id : null;
8293   }
8294   moveElementInDOM(container, element, contentElement, isRemovable) {
8295     const id = this.addPointerInTextLayer(contentElement, isRemovable);
8296     if (!container.hasChildNodes()) {
8297       container.append(element);
8298       return id;
8299     }
8300     const children = Array.from(container.childNodes).filter(node => node !== element);
8301     if (children.length === 0) {
8302       return id;
8303     }
8304     const elementToCompare = contentElement || element;
8305     const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(elementToCompare, node) < 0);
8306     if (index === 0) {
8307       children[0].before(element);
8308     } else {
8309       children[index - 1].after(element);
8310     }
8311     return id;
8312   }
8315 ;// ./web/text_highlighter.js
8316 class TextHighlighter {
8317   #eventAbortController = null;
8318   constructor({
8319     findController,
8320     eventBus,
8321     pageIndex
8322   }) {
8323     this.findController = findController;
8324     this.matches = [];
8325     this.eventBus = eventBus;
8326     this.pageIdx = pageIndex;
8327     this.textDivs = null;
8328     this.textContentItemsStr = null;
8329     this.enabled = false;
8330   }
8331   setTextMapping(divs, texts) {
8332     this.textDivs = divs;
8333     this.textContentItemsStr = texts;
8334   }
8335   enable() {
8336     if (!this.textDivs || !this.textContentItemsStr) {
8337       throw new Error("Text divs and strings have not been set.");
8338     }
8339     if (this.enabled) {
8340       throw new Error("TextHighlighter is already enabled.");
8341     }
8342     this.enabled = true;
8343     if (!this.#eventAbortController) {
8344       this.#eventAbortController = new AbortController();
8345       this.eventBus._on("updatetextlayermatches", evt => {
8346         if (evt.pageIndex === this.pageIdx || evt.pageIndex === -1) {
8347           this._updateMatches();
8348         }
8349       }, {
8350         signal: this.#eventAbortController.signal
8351       });
8352     }
8353     this._updateMatches();
8354   }
8355   disable() {
8356     if (!this.enabled) {
8357       return;
8358     }
8359     this.enabled = false;
8360     this.#eventAbortController?.abort();
8361     this.#eventAbortController = null;
8362     this._updateMatches(true);
8363   }
8364   _convertMatches(matches, matchesLength) {
8365     if (!matches) {
8366       return [];
8367     }
8368     const {
8369       textContentItemsStr
8370     } = this;
8371     let i = 0,
8372       iIndex = 0;
8373     const end = textContentItemsStr.length - 1;
8374     const result = [];
8375     for (let m = 0, mm = matches.length; m < mm; m++) {
8376       let matchIdx = matches[m];
8377       while (i !== end && matchIdx >= iIndex + textContentItemsStr[i].length) {
8378         iIndex += textContentItemsStr[i].length;
8379         i++;
8380       }
8381       if (i === textContentItemsStr.length) {
8382         console.error("Could not find a matching mapping");
8383       }
8384       const match = {
8385         begin: {
8386           divIdx: i,
8387           offset: matchIdx - iIndex
8388         }
8389       };
8390       matchIdx += matchesLength[m];
8391       while (i !== end && matchIdx > iIndex + textContentItemsStr[i].length) {
8392         iIndex += textContentItemsStr[i].length;
8393         i++;
8394       }
8395       match.end = {
8396         divIdx: i,
8397         offset: matchIdx - iIndex
8398       };
8399       result.push(match);
8400     }
8401     return result;
8402   }
8403   _renderMatches(matches) {
8404     if (matches.length === 0) {
8405       return;
8406     }
8407     const {
8408       findController,
8409       pageIdx
8410     } = this;
8411     const {
8412       textContentItemsStr,
8413       textDivs
8414     } = this;
8415     const isSelectedPage = pageIdx === findController.selected.pageIdx;
8416     const selectedMatchIdx = findController.selected.matchIdx;
8417     const highlightAll = findController.state.highlightAll;
8418     let prevEnd = null;
8419     const infinity = {
8420       divIdx: -1,
8421       offset: undefined
8422     };
8423     function beginText(begin, className) {
8424       const divIdx = begin.divIdx;
8425       textDivs[divIdx].textContent = "";
8426       return appendTextToDiv(divIdx, 0, begin.offset, className);
8427     }
8428     function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
8429       let div = textDivs[divIdx];
8430       if (div.nodeType === Node.TEXT_NODE) {
8431         const span = document.createElement("span");
8432         div.before(span);
8433         span.append(div);
8434         textDivs[divIdx] = span;
8435         div = span;
8436       }
8437       const content = textContentItemsStr[divIdx].substring(fromOffset, toOffset);
8438       const node = document.createTextNode(content);
8439       if (className) {
8440         const span = document.createElement("span");
8441         span.className = `${className} appended`;
8442         span.append(node);
8443         div.append(span);
8444         if (className.includes("selected")) {
8445           const {
8446             left
8447           } = span.getClientRects()[0];
8448           const parentLeft = div.getBoundingClientRect().left;
8449           return left - parentLeft;
8450         }
8451         return 0;
8452       }
8453       div.append(node);
8454       return 0;
8455     }
8456     let i0 = selectedMatchIdx,
8457       i1 = i0 + 1;
8458     if (highlightAll) {
8459       i0 = 0;
8460       i1 = matches.length;
8461     } else if (!isSelectedPage) {
8462       return;
8463     }
8464     let lastDivIdx = -1;
8465     let lastOffset = -1;
8466     for (let i = i0; i < i1; i++) {
8467       const match = matches[i];
8468       const begin = match.begin;
8469       if (begin.divIdx === lastDivIdx && begin.offset === lastOffset) {
8470         continue;
8471       }
8472       lastDivIdx = begin.divIdx;
8473       lastOffset = begin.offset;
8474       const end = match.end;
8475       const isSelected = isSelectedPage && i === selectedMatchIdx;
8476       const highlightSuffix = isSelected ? " selected" : "";
8477       let selectedLeft = 0;
8478       if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
8479         if (prevEnd !== null) {
8480           appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
8481         }
8482         beginText(begin);
8483       } else {
8484         appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
8485       }
8486       if (begin.divIdx === end.divIdx) {
8487         selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, end.offset, "highlight" + highlightSuffix);
8488       } else {
8489         selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, "highlight begin" + highlightSuffix);
8490         for (let n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
8491           textDivs[n0].className = "highlight middle" + highlightSuffix;
8492         }
8493         beginText(end, "highlight end" + highlightSuffix);
8494       }
8495       prevEnd = end;
8496       if (isSelected) {
8497         findController.scrollMatchIntoView({
8498           element: textDivs[begin.divIdx],
8499           selectedLeft,
8500           pageIndex: pageIdx,
8501           matchIndex: selectedMatchIdx
8502         });
8503       }
8504     }
8505     if (prevEnd) {
8506       appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
8507     }
8508   }
8509   _updateMatches(reset = false) {
8510     if (!this.enabled && !reset) {
8511       return;
8512     }
8513     const {
8514       findController,
8515       matches,
8516       pageIdx
8517     } = this;
8518     const {
8519       textContentItemsStr,
8520       textDivs
8521     } = this;
8522     let clearedUntilDivIdx = -1;
8523     for (const match of matches) {
8524       const begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
8525       for (let n = begin, end = match.end.divIdx; n <= end; n++) {
8526         const div = textDivs[n];
8527         div.textContent = textContentItemsStr[n];
8528         div.className = "";
8529       }
8530       clearedUntilDivIdx = match.end.divIdx + 1;
8531     }
8532     if (!findController?.highlightMatches || reset) {
8533       return;
8534     }
8535     const pageMatches = findController.pageMatches[pageIdx] || null;
8536     const pageMatchesLength = findController.pageMatchesLength[pageIdx] || null;
8537     this.matches = this._convertMatches(pageMatches, pageMatchesLength);
8538     this._renderMatches(this.matches);
8539   }
8542 ;// ./web/text_layer_builder.js
8545 class TextLayerBuilder {
8546   #enablePermissions = false;
8547   #onAppend = null;
8548   #renderingDone = false;
8549   #textLayer = null;
8550   static #textLayers = new Map();
8551   static #selectionChangeAbortController = null;
8552   constructor({
8553     pdfPage,
8554     highlighter = null,
8555     accessibilityManager = null,
8556     enablePermissions = false,
8557     onAppend = null
8558   }) {
8559     this.pdfPage = pdfPage;
8560     this.highlighter = highlighter;
8561     this.accessibilityManager = accessibilityManager;
8562     this.#enablePermissions = enablePermissions === true;
8563     this.#onAppend = onAppend;
8564     this.div = document.createElement("div");
8565     this.div.tabIndex = 0;
8566     this.div.className = "textLayer";
8567   }
8568   async render({
8569     viewport,
8570     textContentParams = null
8571   }) {
8572     if (this.#renderingDone && this.#textLayer) {
8573       this.#textLayer.update({
8574         viewport,
8575         onBefore: this.hide.bind(this)
8576       });
8577       this.show();
8578       return;
8579     }
8580     this.cancel();
8581     this.#textLayer = new TextLayer({
8582       textContentSource: this.pdfPage.streamTextContent(textContentParams || {
8583         includeMarkedContent: true,
8584         disableNormalization: true
8585       }),
8586       container: this.div,
8587       viewport
8588     });
8589     const {
8590       textDivs,
8591       textContentItemsStr
8592     } = this.#textLayer;
8593     this.highlighter?.setTextMapping(textDivs, textContentItemsStr);
8594     this.accessibilityManager?.setTextMapping(textDivs);
8595     await this.#textLayer.render();
8596     this.#renderingDone = true;
8597     const endOfContent = document.createElement("div");
8598     endOfContent.className = "endOfContent";
8599     this.div.append(endOfContent);
8600     this.#bindMouse(endOfContent);
8601     this.#onAppend?.(this.div);
8602     this.highlighter?.enable();
8603     this.accessibilityManager?.enable();
8604   }
8605   hide() {
8606     if (!this.div.hidden && this.#renderingDone) {
8607       this.highlighter?.disable();
8608       this.div.hidden = true;
8609     }
8610   }
8611   show() {
8612     if (this.div.hidden && this.#renderingDone) {
8613       this.div.hidden = false;
8614       this.highlighter?.enable();
8615     }
8616   }
8617   cancel() {
8618     this.#textLayer?.cancel();
8619     this.#textLayer = null;
8620     this.highlighter?.disable();
8621     this.accessibilityManager?.disable();
8622     TextLayerBuilder.#removeGlobalSelectionListener(this.div);
8623   }
8624   #bindMouse(end) {
8625     const {
8626       div
8627     } = this;
8628     div.addEventListener("mousedown", () => {
8629       div.classList.add("selecting");
8630     });
8631     div.addEventListener("copy", event => {
8632       if (!this.#enablePermissions) {
8633         const selection = document.getSelection();
8634         event.clipboardData.setData("text/plain", removeNullCharacters(normalizeUnicode(selection.toString())));
8635       }
8636       stopEvent(event);
8637     });
8638     TextLayerBuilder.#textLayers.set(div, end);
8639     TextLayerBuilder.#enableGlobalSelectionListener();
8640   }
8641   static #removeGlobalSelectionListener(textLayerDiv) {
8642     this.#textLayers.delete(textLayerDiv);
8643     if (this.#textLayers.size === 0) {
8644       this.#selectionChangeAbortController?.abort();
8645       this.#selectionChangeAbortController = null;
8646     }
8647   }
8648   static #enableGlobalSelectionListener() {
8649     if (this.#selectionChangeAbortController) {
8650       return;
8651     }
8652     this.#selectionChangeAbortController = new AbortController();
8653     const {
8654       signal
8655     } = this.#selectionChangeAbortController;
8656     const reset = (end, textLayer) => {
8657       textLayer.classList.remove("selecting");
8658     };
8659     let isPointerDown = false;
8660     document.addEventListener("pointerdown", () => {
8661       isPointerDown = true;
8662     }, {
8663       signal
8664     });
8665     document.addEventListener("pointerup", () => {
8666       isPointerDown = false;
8667       this.#textLayers.forEach(reset);
8668     }, {
8669       signal
8670     });
8671     window.addEventListener("blur", () => {
8672       isPointerDown = false;
8673       this.#textLayers.forEach(reset);
8674     }, {
8675       signal
8676     });
8677     document.addEventListener("keyup", () => {
8678       if (!isPointerDown) {
8679         this.#textLayers.forEach(reset);
8680       }
8681     }, {
8682       signal
8683     });
8684     document.addEventListener("selectionchange", () => {
8685       const selection = document.getSelection();
8686       if (selection.rangeCount === 0) {
8687         this.#textLayers.forEach(reset);
8688         return;
8689       }
8690       const activeTextLayers = new Set();
8691       for (let i = 0; i < selection.rangeCount; i++) {
8692         const range = selection.getRangeAt(i);
8693         for (const textLayerDiv of this.#textLayers.keys()) {
8694           if (!activeTextLayers.has(textLayerDiv) && range.intersectsNode(textLayerDiv)) {
8695             activeTextLayers.add(textLayerDiv);
8696           }
8697         }
8698       }
8699       for (const [textLayerDiv, endDiv] of this.#textLayers) {
8700         if (activeTextLayers.has(textLayerDiv)) {
8701           textLayerDiv.classList.add("selecting");
8702         } else {
8703           reset(endDiv, textLayerDiv);
8704         }
8705       }
8706     }, {
8707       signal
8708     });
8709   }
8712 ;// ./web/pdf_page_view.js
8726 const DEFAULT_LAYER_PROPERTIES = null;
8727 const LAYERS_ORDER = new Map([["canvasWrapper", 0], ["textLayer", 1], ["annotationLayer", 2], ["annotationEditorLayer", 3], ["xfaLayer", 3]]);
8728 class PDFPageView {
8729   #annotationMode = AnnotationMode.ENABLE_FORMS;
8730   #canvasWrapper = null;
8731   #enableHWA = false;
8732   #hasRestrictedScaling = false;
8733   #isEditing = false;
8734   #layerProperties = null;
8735   #loadingId = null;
8736   #originalViewport = null;
8737   #previousRotation = null;
8738   #scaleRoundX = 1;
8739   #scaleRoundY = 1;
8740   #renderError = null;
8741   #renderingState = RenderingStates.INITIAL;
8742   #textLayerMode = TextLayerMode.ENABLE;
8743   #useThumbnailCanvas = {
8744     directDrawing: true,
8745     initialOptionalContent: true,
8746     regularAnnotations: true
8747   };
8748   #layers = [null, null, null, null];
8749   constructor(options) {
8750     const container = options.container;
8751     const defaultViewport = options.defaultViewport;
8752     this.id = options.id;
8753     this.renderingId = "page" + this.id;
8754     this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES;
8755     this.pdfPage = null;
8756     this.pageLabel = null;
8757     this.rotation = 0;
8758     this.scale = options.scale || DEFAULT_SCALE;
8759     this.viewport = defaultViewport;
8760     this.pdfPageRotate = defaultViewport.rotation;
8761     this._optionalContentConfigPromise = options.optionalContentConfigPromise || null;
8762     this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
8763     this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
8764     this.imageResourcesPath = options.imageResourcesPath || "";
8765     this.maxCanvasPixels = options.maxCanvasPixels ?? AppOptions.get("maxCanvasPixels");
8766     this.pageColors = options.pageColors || null;
8767     this.#enableHWA = options.enableHWA || false;
8768     this.eventBus = options.eventBus;
8769     this.renderingQueue = options.renderingQueue;
8770     this.l10n = options.l10n;
8771     this.renderTask = null;
8772     this.resume = null;
8773     this._annotationCanvasMap = null;
8774     this.annotationLayer = null;
8775     this.annotationEditorLayer = null;
8776     this.textLayer = null;
8777     this.xfaLayer = null;
8778     this.structTreeLayer = null;
8779     this.drawLayer = null;
8780     const div = document.createElement("div");
8781     div.className = "page";
8782     div.setAttribute("data-page-number", this.id);
8783     div.setAttribute("role", "region");
8784     div.setAttribute("data-l10n-id", "pdfjs-page-landmark");
8785     div.setAttribute("data-l10n-args", JSON.stringify({
8786       page: this.id
8787     }));
8788     this.div = div;
8789     this.#setDimensions();
8790     container?.append(div);
8791   }
8792   #addLayer(div, name) {
8793     const pos = LAYERS_ORDER.get(name);
8794     const oldDiv = this.#layers[pos];
8795     this.#layers[pos] = div;
8796     if (oldDiv) {
8797       oldDiv.replaceWith(div);
8798       return;
8799     }
8800     for (let i = pos - 1; i >= 0; i--) {
8801       const layer = this.#layers[i];
8802       if (layer) {
8803         layer.after(div);
8804         return;
8805       }
8806     }
8807     this.div.prepend(div);
8808   }
8809   get renderingState() {
8810     return this.#renderingState;
8811   }
8812   set renderingState(state) {
8813     if (state === this.#renderingState) {
8814       return;
8815     }
8816     this.#renderingState = state;
8817     if (this.#loadingId) {
8818       clearTimeout(this.#loadingId);
8819       this.#loadingId = null;
8820     }
8821     switch (state) {
8822       case RenderingStates.PAUSED:
8823         this.div.classList.remove("loading");
8824         break;
8825       case RenderingStates.RUNNING:
8826         this.div.classList.add("loadingIcon");
8827         this.#loadingId = setTimeout(() => {
8828           this.div.classList.add("loading");
8829           this.#loadingId = null;
8830         }, 0);
8831         break;
8832       case RenderingStates.INITIAL:
8833       case RenderingStates.FINISHED:
8834         this.div.classList.remove("loadingIcon", "loading");
8835         break;
8836     }
8837   }
8838   #setDimensions() {
8839     const {
8840       viewport
8841     } = this;
8842     if (this.pdfPage) {
8843       if (this.#previousRotation === viewport.rotation) {
8844         return;
8845       }
8846       this.#previousRotation = viewport.rotation;
8847     }
8848     setLayerDimensions(this.div, viewport, true, false);
8849   }
8850   setPdfPage(pdfPage) {
8851     this.pdfPage = pdfPage;
8852     this.pdfPageRotate = pdfPage.rotate;
8853     const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
8854     this.viewport = pdfPage.getViewport({
8855       scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
8856       rotation: totalRotation
8857     });
8858     this.#setDimensions();
8859     this.reset();
8860   }
8861   destroy() {
8862     this.reset();
8863     this.pdfPage?.cleanup();
8864   }
8865   hasEditableAnnotations() {
8866     return !!this.annotationLayer?.hasEditableAnnotations();
8867   }
8868   get _textHighlighter() {
8869     return shadow(this, "_textHighlighter", new TextHighlighter({
8870       pageIndex: this.id - 1,
8871       eventBus: this.eventBus,
8872       findController: this.#layerProperties.findController
8873     }));
8874   }
8875   #dispatchLayerRendered(name, error) {
8876     this.eventBus.dispatch(name, {
8877       source: this,
8878       pageNumber: this.id,
8879       error
8880     });
8881   }
8882   async #renderAnnotationLayer() {
8883     let error = null;
8884     try {
8885       await this.annotationLayer.render({
8886         viewport: this.viewport,
8887         intent: "display",
8888         structTreeLayer: this.structTreeLayer
8889       });
8890     } catch (ex) {
8891       console.error("#renderAnnotationLayer:", ex);
8892       error = ex;
8893     } finally {
8894       this.#dispatchLayerRendered("annotationlayerrendered", error);
8895     }
8896   }
8897   async #renderAnnotationEditorLayer() {
8898     let error = null;
8899     try {
8900       await this.annotationEditorLayer.render({
8901         viewport: this.viewport,
8902         intent: "display"
8903       });
8904     } catch (ex) {
8905       console.error("#renderAnnotationEditorLayer:", ex);
8906       error = ex;
8907     } finally {
8908       this.#dispatchLayerRendered("annotationeditorlayerrendered", error);
8909     }
8910   }
8911   async #renderDrawLayer() {
8912     try {
8913       await this.drawLayer.render({
8914         intent: "display"
8915       });
8916     } catch (ex) {
8917       console.error("#renderDrawLayer:", ex);
8918     }
8919   }
8920   async #renderXfaLayer() {
8921     let error = null;
8922     try {
8923       const result = await this.xfaLayer.render({
8924         viewport: this.viewport,
8925         intent: "display"
8926       });
8927       if (result?.textDivs && this._textHighlighter) {
8928         this.#buildXfaTextContentItems(result.textDivs);
8929       }
8930     } catch (ex) {
8931       console.error("#renderXfaLayer:", ex);
8932       error = ex;
8933     } finally {
8934       if (this.xfaLayer?.div) {
8935         this.l10n.pause();
8936         this.#addLayer(this.xfaLayer.div, "xfaLayer");
8937         this.l10n.resume();
8938       }
8939       this.#dispatchLayerRendered("xfalayerrendered", error);
8940     }
8941   }
8942   async #renderTextLayer() {
8943     if (!this.textLayer) {
8944       return;
8945     }
8946     let error = null;
8947     try {
8948       await this.textLayer.render({
8949         viewport: this.viewport
8950       });
8951     } catch (ex) {
8952       if (ex instanceof AbortException) {
8953         return;
8954       }
8955       console.error("#renderTextLayer:", ex);
8956       error = ex;
8957     }
8958     this.#dispatchLayerRendered("textlayerrendered", error);
8959     this.#renderStructTreeLayer();
8960   }
8961   async #renderStructTreeLayer() {
8962     if (!this.textLayer) {
8963       return;
8964     }
8965     const treeDom = await this.structTreeLayer?.render();
8966     if (treeDom) {
8967       this.l10n.pause();
8968       this.structTreeLayer?.addElementsToTextLayer();
8969       if (this.canvas && treeDom.parentNode !== this.canvas) {
8970         this.canvas.append(treeDom);
8971       }
8972       this.l10n.resume();
8973     }
8974     this.structTreeLayer?.show();
8975   }
8976   async #buildXfaTextContentItems(textDivs) {
8977     const text = await this.pdfPage.getTextContent();
8978     const items = [];
8979     for (const item of text.items) {
8980       items.push(item.str);
8981     }
8982     this._textHighlighter.setTextMapping(textDivs, items);
8983     this._textHighlighter.enable();
8984   }
8985   #resetCanvas() {
8986     const {
8987       canvas
8988     } = this;
8989     if (!canvas) {
8990       return;
8991     }
8992     canvas.remove();
8993     canvas.width = canvas.height = 0;
8994     this.canvas = null;
8995     this.#originalViewport = null;
8996   }
8997   reset({
8998     keepAnnotationLayer = false,
8999     keepAnnotationEditorLayer = false,
9000     keepXfaLayer = false,
9001     keepTextLayer = false,
9002     keepCanvasWrapper = false
9003   } = {}) {
9004     this.cancelRendering({
9005       keepAnnotationLayer,
9006       keepAnnotationEditorLayer,
9007       keepXfaLayer,
9008       keepTextLayer
9009     });
9010     this.renderingState = RenderingStates.INITIAL;
9011     const div = this.div;
9012     const childNodes = div.childNodes,
9013       annotationLayerNode = keepAnnotationLayer && this.annotationLayer?.div || null,
9014       annotationEditorLayerNode = keepAnnotationEditorLayer && this.annotationEditorLayer?.div || null,
9015       xfaLayerNode = keepXfaLayer && this.xfaLayer?.div || null,
9016       textLayerNode = keepTextLayer && this.textLayer?.div || null,
9017       canvasWrapperNode = keepCanvasWrapper && this.#canvasWrapper || null;
9018     for (let i = childNodes.length - 1; i >= 0; i--) {
9019       const node = childNodes[i];
9020       switch (node) {
9021         case annotationLayerNode:
9022         case annotationEditorLayerNode:
9023         case xfaLayerNode:
9024         case textLayerNode:
9025         case canvasWrapperNode:
9026           continue;
9027       }
9028       node.remove();
9029       const layerIndex = this.#layers.indexOf(node);
9030       if (layerIndex >= 0) {
9031         this.#layers[layerIndex] = null;
9032       }
9033     }
9034     div.removeAttribute("data-loaded");
9035     if (annotationLayerNode) {
9036       this.annotationLayer.hide();
9037     }
9038     if (annotationEditorLayerNode) {
9039       this.annotationEditorLayer.hide();
9040     }
9041     if (xfaLayerNode) {
9042       this.xfaLayer.hide();
9043     }
9044     if (textLayerNode) {
9045       this.textLayer.hide();
9046     }
9047     this.structTreeLayer?.hide();
9048     if (!keepCanvasWrapper && this.#canvasWrapper) {
9049       this.#canvasWrapper = null;
9050       this.#resetCanvas();
9051     }
9052   }
9053   toggleEditingMode(isEditing) {
9054     this.#isEditing = isEditing;
9055     if (!this.hasEditableAnnotations()) {
9056       return;
9057     }
9058     this.reset({
9059       keepAnnotationLayer: true,
9060       keepAnnotationEditorLayer: true,
9061       keepXfaLayer: true,
9062       keepTextLayer: true,
9063       keepCanvasWrapper: true
9064     });
9065   }
9066   update({
9067     scale = 0,
9068     rotation = null,
9069     optionalContentConfigPromise = null,
9070     drawingDelay = -1
9071   }) {
9072     this.scale = scale || this.scale;
9073     if (typeof rotation === "number") {
9074       this.rotation = rotation;
9075     }
9076     if (optionalContentConfigPromise instanceof Promise) {
9077       this._optionalContentConfigPromise = optionalContentConfigPromise;
9078       optionalContentConfigPromise.then(optionalContentConfig => {
9079         if (optionalContentConfigPromise !== this._optionalContentConfigPromise) {
9080           return;
9081         }
9082         this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility;
9083       });
9084     }
9085     this.#useThumbnailCanvas.directDrawing = true;
9086     const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
9087     this.viewport = this.viewport.clone({
9088       scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
9089       rotation: totalRotation
9090     });
9091     this.#setDimensions();
9092     if (this.canvas) {
9093       let onlyCssZoom = false;
9094       if (this.#hasRestrictedScaling) {
9095         if (this.maxCanvasPixels > 0) {
9096           const {
9097             width,
9098             height
9099           } = this.viewport;
9100           const {
9101             sx,
9102             sy
9103           } = this.outputScale;
9104           onlyCssZoom = (Math.floor(width) * sx | 0) * (Math.floor(height) * sy | 0) > this.maxCanvasPixels;
9105         }
9106       }
9107       const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
9108       if (postponeDrawing || onlyCssZoom) {
9109         if (postponeDrawing && !onlyCssZoom && this.renderingState !== RenderingStates.FINISHED) {
9110           this.cancelRendering({
9111             keepAnnotationLayer: true,
9112             keepAnnotationEditorLayer: true,
9113             keepXfaLayer: true,
9114             keepTextLayer: true,
9115             cancelExtraDelay: drawingDelay
9116           });
9117           this.renderingState = RenderingStates.FINISHED;
9118           this.#useThumbnailCanvas.directDrawing = false;
9119         }
9120         this.cssTransform({
9121           redrawAnnotationLayer: true,
9122           redrawAnnotationEditorLayer: true,
9123           redrawXfaLayer: true,
9124           redrawTextLayer: !postponeDrawing,
9125           hideTextLayer: postponeDrawing
9126         });
9127         if (postponeDrawing) {
9128           return;
9129         }
9130         this.eventBus.dispatch("pagerendered", {
9131           source: this,
9132           pageNumber: this.id,
9133           cssTransform: true,
9134           timestamp: performance.now(),
9135           error: this.#renderError
9136         });
9137         return;
9138       }
9139     }
9140     this.cssTransform({});
9141     this.reset({
9142       keepAnnotationLayer: true,
9143       keepAnnotationEditorLayer: true,
9144       keepXfaLayer: true,
9145       keepTextLayer: true,
9146       keepCanvasWrapper: true
9147     });
9148   }
9149   cancelRendering({
9150     keepAnnotationLayer = false,
9151     keepAnnotationEditorLayer = false,
9152     keepXfaLayer = false,
9153     keepTextLayer = false,
9154     cancelExtraDelay = 0
9155   } = {}) {
9156     if (this.renderTask) {
9157       this.renderTask.cancel(cancelExtraDelay);
9158       this.renderTask = null;
9159     }
9160     this.resume = null;
9161     if (this.textLayer && (!keepTextLayer || !this.textLayer.div)) {
9162       this.textLayer.cancel();
9163       this.textLayer = null;
9164     }
9165     if (this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div)) {
9166       this.annotationLayer.cancel();
9167       this.annotationLayer = null;
9168       this._annotationCanvasMap = null;
9169     }
9170     if (this.structTreeLayer && !this.textLayer) {
9171       this.structTreeLayer = null;
9172     }
9173     if (this.annotationEditorLayer && (!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)) {
9174       if (this.drawLayer) {
9175         this.drawLayer.cancel();
9176         this.drawLayer = null;
9177       }
9178       this.annotationEditorLayer.cancel();
9179       this.annotationEditorLayer = null;
9180     }
9181     if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
9182       this.xfaLayer.cancel();
9183       this.xfaLayer = null;
9184       this._textHighlighter?.disable();
9185     }
9186   }
9187   cssTransform({
9188     redrawAnnotationLayer = false,
9189     redrawAnnotationEditorLayer = false,
9190     redrawXfaLayer = false,
9191     redrawTextLayer = false,
9192     hideTextLayer = false
9193   }) {
9194     const {
9195       canvas
9196     } = this;
9197     if (!canvas) {
9198       return;
9199     }
9200     const originalViewport = this.#originalViewport;
9201     if (this.viewport !== originalViewport) {
9202       const relativeRotation = (360 + this.viewport.rotation - originalViewport.rotation) % 360;
9203       if (relativeRotation === 90 || relativeRotation === 270) {
9204         const {
9205           width,
9206           height
9207         } = this.viewport;
9208         const scaleX = height / width;
9209         const scaleY = width / height;
9210         canvas.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX},${scaleY})`;
9211       } else {
9212         canvas.style.transform = relativeRotation === 0 ? "" : `rotate(${relativeRotation}deg)`;
9213       }
9214     }
9215     if (redrawAnnotationLayer && this.annotationLayer) {
9216       this.#renderAnnotationLayer();
9217     }
9218     if (redrawAnnotationEditorLayer && this.annotationEditorLayer) {
9219       if (this.drawLayer) {
9220         this.#renderDrawLayer();
9221       }
9222       this.#renderAnnotationEditorLayer();
9223     }
9224     if (redrawXfaLayer && this.xfaLayer) {
9225       this.#renderXfaLayer();
9226     }
9227     if (this.textLayer) {
9228       if (hideTextLayer) {
9229         this.textLayer.hide();
9230         this.structTreeLayer?.hide();
9231       } else if (redrawTextLayer) {
9232         this.#renderTextLayer();
9233       }
9234     }
9235   }
9236   get width() {
9237     return this.viewport.width;
9238   }
9239   get height() {
9240     return this.viewport.height;
9241   }
9242   getPagePoint(x, y) {
9243     return this.viewport.convertToPdfPoint(x, y);
9244   }
9245   async #finishRenderTask(renderTask, error = null) {
9246     if (renderTask === this.renderTask) {
9247       this.renderTask = null;
9248     }
9249     if (error instanceof RenderingCancelledException) {
9250       this.#renderError = null;
9251       return;
9252     }
9253     this.#renderError = error;
9254     this.renderingState = RenderingStates.FINISHED;
9255     this.#useThumbnailCanvas.regularAnnotations = !renderTask.separateAnnots;
9256     this.eventBus.dispatch("pagerendered", {
9257       source: this,
9258       pageNumber: this.id,
9259       cssTransform: false,
9260       timestamp: performance.now(),
9261       error: this.#renderError
9262     });
9263     if (error) {
9264       throw error;
9265     }
9266   }
9267   async draw() {
9268     if (this.renderingState !== RenderingStates.INITIAL) {
9269       console.error("Must be in new state before drawing");
9270       this.reset();
9271     }
9272     const {
9273       div,
9274       l10n,
9275       pageColors,
9276       pdfPage,
9277       viewport
9278     } = this;
9279     if (!pdfPage) {
9280       this.renderingState = RenderingStates.FINISHED;
9281       throw new Error("pdfPage is not loaded");
9282     }
9283     this.renderingState = RenderingStates.RUNNING;
9284     let canvasWrapper = this.#canvasWrapper;
9285     if (!canvasWrapper) {
9286       canvasWrapper = this.#canvasWrapper = document.createElement("div");
9287       canvasWrapper.classList.add("canvasWrapper");
9288       this.#addLayer(canvasWrapper, "canvasWrapper");
9289     }
9290     if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) {
9291       this._accessibilityManager ||= new TextAccessibilityManager();
9292       this.textLayer = new TextLayerBuilder({
9293         pdfPage,
9294         highlighter: this._textHighlighter,
9295         accessibilityManager: this._accessibilityManager,
9296         enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS,
9297         onAppend: textLayerDiv => {
9298           this.l10n.pause();
9299           this.#addLayer(textLayerDiv, "textLayer");
9300           this.l10n.resume();
9301         }
9302       });
9303     }
9304     if (!this.annotationLayer && this.#annotationMode !== AnnotationMode.DISABLE) {
9305       const {
9306         annotationStorage,
9307         annotationEditorUIManager,
9308         downloadManager,
9309         enableScripting,
9310         fieldObjectsPromise,
9311         hasJSActionsPromise,
9312         linkService
9313       } = this.#layerProperties;
9314       this._annotationCanvasMap ||= new Map();
9315       this.annotationLayer = new AnnotationLayerBuilder({
9316         pdfPage,
9317         annotationStorage,
9318         imageResourcesPath: this.imageResourcesPath,
9319         renderForms: this.#annotationMode === AnnotationMode.ENABLE_FORMS,
9320         linkService,
9321         downloadManager,
9322         enableScripting,
9323         hasJSActionsPromise,
9324         fieldObjectsPromise,
9325         annotationCanvasMap: this._annotationCanvasMap,
9326         accessibilityManager: this._accessibilityManager,
9327         annotationEditorUIManager,
9328         onAppend: annotationLayerDiv => {
9329           this.#addLayer(annotationLayerDiv, "annotationLayer");
9330         }
9331       });
9332     }
9333     const renderContinueCallback = cont => {
9334       showCanvas?.(false);
9335       if (this.renderingQueue && !this.renderingQueue.isHighestPriority(this)) {
9336         this.renderingState = RenderingStates.PAUSED;
9337         this.resume = () => {
9338           this.renderingState = RenderingStates.RUNNING;
9339           cont();
9340         };
9341         return;
9342       }
9343       cont();
9344     };
9345     const {
9346       width,
9347       height
9348     } = viewport;
9349     const canvas = document.createElement("canvas");
9350     canvas.setAttribute("role", "presentation");
9351     const hasHCM = !!(pageColors?.background && pageColors?.foreground);
9352     const prevCanvas = this.canvas;
9353     const updateOnFirstShow = !prevCanvas && !hasHCM;
9354     this.canvas = canvas;
9355     this.#originalViewport = viewport;
9356     let showCanvas = isLastShow => {
9357       if (updateOnFirstShow) {
9358         canvasWrapper.prepend(canvas);
9359         showCanvas = null;
9360         return;
9361       }
9362       if (!isLastShow) {
9363         return;
9364       }
9365       if (prevCanvas) {
9366         prevCanvas.replaceWith(canvas);
9367         prevCanvas.width = prevCanvas.height = 0;
9368       } else {
9369         canvasWrapper.prepend(canvas);
9370       }
9371       showCanvas = null;
9372     };
9373     const ctx = canvas.getContext("2d", {
9374       alpha: false,
9375       willReadFrequently: !this.#enableHWA
9376     });
9377     const outputScale = this.outputScale = new OutputScale();
9378     if (this.maxCanvasPixels > 0) {
9379       const pixelsInViewport = width * height;
9380       const maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport);
9381       if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
9382         outputScale.sx = maxScale;
9383         outputScale.sy = maxScale;
9384         this.#hasRestrictedScaling = true;
9385       } else {
9386         this.#hasRestrictedScaling = false;
9387       }
9388     }
9389     const sfx = approximateFraction(outputScale.sx);
9390     const sfy = approximateFraction(outputScale.sy);
9391     const canvasWidth = canvas.width = floorToDivide(calcRound(width * outputScale.sx), sfx[0]);
9392     const canvasHeight = canvas.height = floorToDivide(calcRound(height * outputScale.sy), sfy[0]);
9393     const pageWidth = floorToDivide(calcRound(width), sfx[1]);
9394     const pageHeight = floorToDivide(calcRound(height), sfy[1]);
9395     outputScale.sx = canvasWidth / pageWidth;
9396     outputScale.sy = canvasHeight / pageHeight;
9397     if (this.#scaleRoundX !== sfx[1]) {
9398       div.style.setProperty("--scale-round-x", `${sfx[1]}px`);
9399       this.#scaleRoundX = sfx[1];
9400     }
9401     if (this.#scaleRoundY !== sfy[1]) {
9402       div.style.setProperty("--scale-round-y", `${sfy[1]}px`);
9403       this.#scaleRoundY = sfy[1];
9404     }
9405     const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;
9406     const renderContext = {
9407       canvasContext: ctx,
9408       transform,
9409       viewport,
9410       annotationMode: this.#annotationMode,
9411       optionalContentConfigPromise: this._optionalContentConfigPromise,
9412       annotationCanvasMap: this._annotationCanvasMap,
9413       pageColors,
9414       isEditing: this.#isEditing
9415     };
9416     const renderTask = this.renderTask = pdfPage.render(renderContext);
9417     renderTask.onContinue = renderContinueCallback;
9418     const resultPromise = renderTask.promise.then(async () => {
9419       showCanvas?.(true);
9420       await this.#finishRenderTask(renderTask);
9421       this.structTreeLayer ||= new StructTreeLayerBuilder(pdfPage, viewport.rawDims);
9422       this.#renderTextLayer();
9423       if (this.annotationLayer) {
9424         await this.#renderAnnotationLayer();
9425       }
9426       const {
9427         annotationEditorUIManager
9428       } = this.#layerProperties;
9429       if (!annotationEditorUIManager) {
9430         return;
9431       }
9432       this.drawLayer ||= new DrawLayerBuilder({
9433         pageIndex: this.id
9434       });
9435       await this.#renderDrawLayer();
9436       this.drawLayer.setParent(canvasWrapper);
9437       this.annotationEditorLayer ||= new AnnotationEditorLayerBuilder({
9438         uiManager: annotationEditorUIManager,
9439         pdfPage,
9440         l10n,
9441         structTreeLayer: this.structTreeLayer,
9442         accessibilityManager: this._accessibilityManager,
9443         annotationLayer: this.annotationLayer?.annotationLayer,
9444         textLayer: this.textLayer,
9445         drawLayer: this.drawLayer.getDrawLayer(),
9446         onAppend: annotationEditorLayerDiv => {
9447           this.#addLayer(annotationEditorLayerDiv, "annotationEditorLayer");
9448         }
9449       });
9450       this.#renderAnnotationEditorLayer();
9451     }, error => {
9452       if (!(error instanceof RenderingCancelledException)) {
9453         showCanvas?.(true);
9454       } else {
9455         prevCanvas?.remove();
9456         this.#resetCanvas();
9457       }
9458       return this.#finishRenderTask(renderTask, error);
9459     });
9460     if (pdfPage.isPureXfa) {
9461       if (!this.xfaLayer) {
9462         const {
9463           annotationStorage,
9464           linkService
9465         } = this.#layerProperties;
9466         this.xfaLayer = new XfaLayerBuilder({
9467           pdfPage,
9468           annotationStorage,
9469           linkService
9470         });
9471       }
9472       this.#renderXfaLayer();
9473     }
9474     div.setAttribute("data-loaded", true);
9475     this.eventBus.dispatch("pagerender", {
9476       source: this,
9477       pageNumber: this.id
9478     });
9479     return resultPromise;
9480   }
9481   setPageLabel(label) {
9482     this.pageLabel = typeof label === "string" ? label : null;
9483     this.div.setAttribute("data-l10n-args", JSON.stringify({
9484       page: this.pageLabel ?? this.id
9485     }));
9486     if (this.pageLabel !== null) {
9487       this.div.setAttribute("data-page-label", this.pageLabel);
9488     } else {
9489       this.div.removeAttribute("data-page-label");
9490     }
9491   }
9492   get thumbnailCanvas() {
9493     const {
9494       directDrawing,
9495       initialOptionalContent,
9496       regularAnnotations
9497     } = this.#useThumbnailCanvas;
9498     return directDrawing && initialOptionalContent && regularAnnotations ? this.canvas : null;
9499   }
9502 ;// ./web/pdf_viewer.js
9509 const DEFAULT_CACHE_SIZE = 10;
9510 const PagesCountLimit = {
9511   FORCE_SCROLL_MODE_PAGE: 10000,
9512   FORCE_LAZY_PAGE_INIT: 5000,
9513   PAUSE_EAGER_PAGE_INIT: 250
9515 function isValidAnnotationEditorMode(mode) {
9516   return Object.values(AnnotationEditorType).includes(mode) && mode !== AnnotationEditorType.DISABLE;
9518 class PDFPageViewBuffer {
9519   #buf = new Set();
9520   #size = 0;
9521   constructor(size) {
9522     this.#size = size;
9523   }
9524   push(view) {
9525     const buf = this.#buf;
9526     if (buf.has(view)) {
9527       buf.delete(view);
9528     }
9529     buf.add(view);
9530     if (buf.size > this.#size) {
9531       this.#destroyFirstView();
9532     }
9533   }
9534   resize(newSize, idsToKeep = null) {
9535     this.#size = newSize;
9536     const buf = this.#buf;
9537     if (idsToKeep) {
9538       const ii = buf.size;
9539       let i = 1;
9540       for (const view of buf) {
9541         if (idsToKeep.has(view.id)) {
9542           buf.delete(view);
9543           buf.add(view);
9544         }
9545         if (++i > ii) {
9546           break;
9547         }
9548       }
9549     }
9550     while (buf.size > this.#size) {
9551       this.#destroyFirstView();
9552     }
9553   }
9554   has(view) {
9555     return this.#buf.has(view);
9556   }
9557   [Symbol.iterator]() {
9558     return this.#buf.keys();
9559   }
9560   #destroyFirstView() {
9561     const firstView = this.#buf.keys().next().value;
9562     firstView?.destroy();
9563     this.#buf.delete(firstView);
9564   }
9566 class PDFViewer {
9567   #buffer = null;
9568   #altTextManager = null;
9569   #annotationEditorHighlightColors = null;
9570   #annotationEditorMode = AnnotationEditorType.NONE;
9571   #annotationEditorUIManager = null;
9572   #annotationMode = AnnotationMode.ENABLE_FORMS;
9573   #containerTopLeft = null;
9574   #editorUndoBar = null;
9575   #enableHWA = false;
9576   #enableHighlightFloatingButton = false;
9577   #enablePermissions = false;
9578   #enableUpdatedAddImage = false;
9579   #enableNewAltTextWhenAddingImage = false;
9580   #eventAbortController = null;
9581   #mlManager = null;
9582   #switchAnnotationEditorModeAC = null;
9583   #switchAnnotationEditorModeTimeoutId = null;
9584   #getAllTextInProgress = false;
9585   #hiddenCopyElement = null;
9586   #interruptCopyCondition = false;
9587   #previousContainerHeight = 0;
9588   #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
9589   #scrollModePageState = null;
9590   #scaleTimeoutId = null;
9591   #supportsPinchToZoom = true;
9592   #textLayerMode = TextLayerMode.ENABLE;
9593   constructor(options) {
9594     const viewerVersion = "5.0.71";
9595     if (version !== viewerVersion) {
9596       throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
9597     }
9598     this.container = options.container;
9599     this.viewer = options.viewer || options.container.firstElementChild;
9600     this.#resizeObserver.observe(this.container);
9601     this.eventBus = options.eventBus;
9602     this.linkService = options.linkService || new SimpleLinkService();
9603     this.downloadManager = options.downloadManager || null;
9604     this.findController = options.findController || null;
9605     this.#altTextManager = options.altTextManager || null;
9606     this.#editorUndoBar = options.editorUndoBar || null;
9607     if (this.findController) {
9608       this.findController.onIsPageVisible = pageNumber => this._getVisiblePages().ids.has(pageNumber);
9609     }
9610     this._scriptingManager = options.scriptingManager || null;
9611     this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
9612     this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
9613     this.#annotationEditorMode = options.annotationEditorMode ?? AnnotationEditorType.NONE;
9614     this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null;
9615     this.#enableHighlightFloatingButton = options.enableHighlightFloatingButton === true;
9616     this.#enableUpdatedAddImage = options.enableUpdatedAddImage === true;
9617     this.#enableNewAltTextWhenAddingImage = options.enableNewAltTextWhenAddingImage === true;
9618     this.imageResourcesPath = options.imageResourcesPath || "";
9619     this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
9620     this.maxCanvasPixels = options.maxCanvasPixels;
9621     this.l10n = options.l10n;
9622     this.#enablePermissions = options.enablePermissions || false;
9623     this.pageColors = options.pageColors || null;
9624     this.#mlManager = options.mlManager || null;
9625     this.#enableHWA = options.enableHWA || false;
9626     this.#supportsPinchToZoom = options.supportsPinchToZoom !== false;
9627     this.defaultRenderingQueue = !options.renderingQueue;
9628     this.renderingQueue = options.renderingQueue;
9629     const {
9630       abortSignal
9631     } = options;
9632     abortSignal?.addEventListener("abort", () => {
9633       this.#resizeObserver.disconnect();
9634       this.#resizeObserver = null;
9635     }, {
9636       once: true
9637     });
9638     this.scroll = watchScroll(this.container, this._scrollUpdate.bind(this), abortSignal);
9639     this.presentationModeState = PresentationModeState.UNKNOWN;
9640     this._resetView();
9641     this.#updateContainerHeightCss();
9642     this.eventBus._on("thumbnailrendered", ({
9643       pageNumber,
9644       pdfPage
9645     }) => {
9646       const pageView = this._pages[pageNumber - 1];
9647       if (!this.#buffer.has(pageView)) {
9648         pdfPage?.cleanup();
9649       }
9650     });
9651   }
9652   get pagesCount() {
9653     return this._pages.length;
9654   }
9655   getPageView(index) {
9656     return this._pages[index];
9657   }
9658   getCachedPageViews() {
9659     return new Set(this.#buffer);
9660   }
9661   get pageViewsReady() {
9662     return this._pages.every(pageView => pageView?.pdfPage);
9663   }
9664   get renderForms() {
9665     return this.#annotationMode === AnnotationMode.ENABLE_FORMS;
9666   }
9667   get enableScripting() {
9668     return !!this._scriptingManager;
9669   }
9670   get currentPageNumber() {
9671     return this._currentPageNumber;
9672   }
9673   set currentPageNumber(val) {
9674     if (!Number.isInteger(val)) {
9675       throw new Error("Invalid page number.");
9676     }
9677     if (!this.pdfDocument) {
9678       return;
9679     }
9680     if (!this._setCurrentPageNumber(val, true)) {
9681       console.error(`currentPageNumber: "${val}" is not a valid page.`);
9682     }
9683   }
9684   _setCurrentPageNumber(val, resetCurrentPageView = false) {
9685     if (this._currentPageNumber === val) {
9686       if (resetCurrentPageView) {
9687         this.#resetCurrentPageView();
9688       }
9689       return true;
9690     }
9691     if (!(0 < val && val <= this.pagesCount)) {
9692       return false;
9693     }
9694     const previous = this._currentPageNumber;
9695     this._currentPageNumber = val;
9696     this.eventBus.dispatch("pagechanging", {
9697       source: this,
9698       pageNumber: val,
9699       pageLabel: this._pageLabels?.[val - 1] ?? null,
9700       previous
9701     });
9702     if (resetCurrentPageView) {
9703       this.#resetCurrentPageView();
9704     }
9705     return true;
9706   }
9707   get currentPageLabel() {
9708     return this._pageLabels?.[this._currentPageNumber - 1] ?? null;
9709   }
9710   set currentPageLabel(val) {
9711     if (!this.pdfDocument) {
9712       return;
9713     }
9714     let page = val | 0;
9715     if (this._pageLabels) {
9716       const i = this._pageLabels.indexOf(val);
9717       if (i >= 0) {
9718         page = i + 1;
9719       }
9720     }
9721     if (!this._setCurrentPageNumber(page, true)) {
9722       console.error(`currentPageLabel: "${val}" is not a valid page.`);
9723     }
9724   }
9725   get currentScale() {
9726     return this._currentScale !== UNKNOWN_SCALE ? this._currentScale : DEFAULT_SCALE;
9727   }
9728   set currentScale(val) {
9729     if (isNaN(val)) {
9730       throw new Error("Invalid numeric scale.");
9731     }
9732     if (!this.pdfDocument) {
9733       return;
9734     }
9735     this.#setScale(val, {
9736       noScroll: false
9737     });
9738   }
9739   get currentScaleValue() {
9740     return this._currentScaleValue;
9741   }
9742   set currentScaleValue(val) {
9743     if (!this.pdfDocument) {
9744       return;
9745     }
9746     this.#setScale(val, {
9747       noScroll: false
9748     });
9749   }
9750   get pagesRotation() {
9751     return this._pagesRotation;
9752   }
9753   set pagesRotation(rotation) {
9754     if (!isValidRotation(rotation)) {
9755       throw new Error("Invalid pages rotation angle.");
9756     }
9757     if (!this.pdfDocument) {
9758       return;
9759     }
9760     rotation %= 360;
9761     if (rotation < 0) {
9762       rotation += 360;
9763     }
9764     if (this._pagesRotation === rotation) {
9765       return;
9766     }
9767     this._pagesRotation = rotation;
9768     const pageNumber = this._currentPageNumber;
9769     this.refresh(true, {
9770       rotation
9771     });
9772     if (this._currentScaleValue) {
9773       this.#setScale(this._currentScaleValue, {
9774         noScroll: true
9775       });
9776     }
9777     this.eventBus.dispatch("rotationchanging", {
9778       source: this,
9779       pagesRotation: rotation,
9780       pageNumber
9781     });
9782     if (this.defaultRenderingQueue) {
9783       this.update();
9784     }
9785   }
9786   get firstPagePromise() {
9787     return this.pdfDocument ? this._firstPageCapability.promise : null;
9788   }
9789   get onePageRendered() {
9790     return this.pdfDocument ? this._onePageRenderedCapability.promise : null;
9791   }
9792   get pagesPromise() {
9793     return this.pdfDocument ? this._pagesCapability.promise : null;
9794   }
9795   get _layerProperties() {
9796     const self = this;
9797     return shadow(this, "_layerProperties", {
9798       get annotationEditorUIManager() {
9799         return self.#annotationEditorUIManager;
9800       },
9801       get annotationStorage() {
9802         return self.pdfDocument?.annotationStorage;
9803       },
9804       get downloadManager() {
9805         return self.downloadManager;
9806       },
9807       get enableScripting() {
9808         return !!self._scriptingManager;
9809       },
9810       get fieldObjectsPromise() {
9811         return self.pdfDocument?.getFieldObjects();
9812       },
9813       get findController() {
9814         return self.findController;
9815       },
9816       get hasJSActionsPromise() {
9817         return self.pdfDocument?.hasJSActions();
9818       },
9819       get linkService() {
9820         return self.linkService;
9821       }
9822     });
9823   }
9824   #initializePermissions(permissions) {
9825     const params = {
9826       annotationEditorMode: this.#annotationEditorMode,
9827       annotationMode: this.#annotationMode,
9828       textLayerMode: this.#textLayerMode
9829     };
9830     if (!permissions) {
9831       return params;
9832     }
9833     if (!permissions.includes(PermissionFlag.COPY) && this.#textLayerMode === TextLayerMode.ENABLE) {
9834       params.textLayerMode = TextLayerMode.ENABLE_PERMISSIONS;
9835     }
9836     if (!permissions.includes(PermissionFlag.MODIFY_CONTENTS)) {
9837       params.annotationEditorMode = AnnotationEditorType.DISABLE;
9838     }
9839     if (!permissions.includes(PermissionFlag.MODIFY_ANNOTATIONS) && !permissions.includes(PermissionFlag.FILL_INTERACTIVE_FORMS) && this.#annotationMode === AnnotationMode.ENABLE_FORMS) {
9840       params.annotationMode = AnnotationMode.ENABLE;
9841     }
9842     return params;
9843   }
9844   async #onePageRenderedOrForceFetch(signal) {
9845     if (document.visibilityState === "hidden" || !this.container.offsetParent || this._getVisiblePages().views.length === 0) {
9846       return;
9847     }
9848     const hiddenCapability = Promise.withResolvers(),
9849       ac = new AbortController();
9850     document.addEventListener("visibilitychange", () => {
9851       if (document.visibilityState === "hidden") {
9852         hiddenCapability.resolve();
9853       }
9854     }, {
9855       signal: AbortSignal.any([signal, ac.signal])
9856     });
9857     await Promise.race([this._onePageRenderedCapability.promise, hiddenCapability.promise]);
9858     ac.abort();
9859   }
9860   async getAllText() {
9861     const texts = [];
9862     const buffer = [];
9863     for (let pageNum = 1, pagesCount = this.pdfDocument.numPages; pageNum <= pagesCount; ++pageNum) {
9864       if (this.#interruptCopyCondition) {
9865         return null;
9866       }
9867       buffer.length = 0;
9868       const page = await this.pdfDocument.getPage(pageNum);
9869       const {
9870         items
9871       } = await page.getTextContent();
9872       for (const item of items) {
9873         if (item.str) {
9874           buffer.push(item.str);
9875         }
9876         if (item.hasEOL) {
9877           buffer.push("\n");
9878         }
9879       }
9880       texts.push(removeNullCharacters(buffer.join("")));
9881     }
9882     return texts.join("\n");
9883   }
9884   #copyCallback(textLayerMode, event) {
9885     const selection = document.getSelection();
9886     const {
9887       focusNode,
9888       anchorNode
9889     } = selection;
9890     if (anchorNode && focusNode && selection.containsNode(this.#hiddenCopyElement)) {
9891       if (this.#getAllTextInProgress || textLayerMode === TextLayerMode.ENABLE_PERMISSIONS) {
9892         stopEvent(event);
9893         return;
9894       }
9895       this.#getAllTextInProgress = true;
9896       const {
9897         classList
9898       } = this.viewer;
9899       classList.add("copyAll");
9900       const ac = new AbortController();
9901       window.addEventListener("keydown", ev => this.#interruptCopyCondition = ev.key === "Escape", {
9902         signal: ac.signal
9903       });
9904       this.getAllText().then(async text => {
9905         if (text !== null) {
9906           await navigator.clipboard.writeText(text);
9907         }
9908       }).catch(reason => {
9909         console.warn(`Something goes wrong when extracting the text: ${reason.message}`);
9910       }).finally(() => {
9911         this.#getAllTextInProgress = false;
9912         this.#interruptCopyCondition = false;
9913         ac.abort();
9914         classList.remove("copyAll");
9915       });
9916       stopEvent(event);
9917     }
9918   }
9919   setDocument(pdfDocument) {
9920     if (this.pdfDocument) {
9921       this.eventBus.dispatch("pagesdestroy", {
9922         source: this
9923       });
9924       this._cancelRendering();
9925       this._resetView();
9926       this.findController?.setDocument(null);
9927       this._scriptingManager?.setDocument(null);
9928       this.#annotationEditorUIManager?.destroy();
9929       this.#annotationEditorUIManager = null;
9930     }
9931     this.pdfDocument = pdfDocument;
9932     if (!pdfDocument) {
9933       return;
9934     }
9935     const pagesCount = pdfDocument.numPages;
9936     const firstPagePromise = pdfDocument.getPage(1);
9937     const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
9938       intent: "display"
9939     });
9940     const permissionsPromise = this.#enablePermissions ? pdfDocument.getPermissions() : Promise.resolve();
9941     const {
9942       eventBus,
9943       pageColors,
9944       viewer
9945     } = this;
9946     this.#eventAbortController = new AbortController();
9947     const {
9948       signal
9949     } = this.#eventAbortController;
9950     if (pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {
9951       console.warn("Forcing PAGE-scrolling for performance reasons, given the length of the document.");
9952       const mode = this._scrollMode = ScrollMode.PAGE;
9953       eventBus.dispatch("scrollmodechanged", {
9954         source: this,
9955         mode
9956       });
9957     }
9958     this._pagesCapability.promise.then(() => {
9959       eventBus.dispatch("pagesloaded", {
9960         source: this,
9961         pagesCount
9962       });
9963     }, () => {});
9964     const onBeforeDraw = evt => {
9965       const pageView = this._pages[evt.pageNumber - 1];
9966       if (!pageView) {
9967         return;
9968       }
9969       this.#buffer.push(pageView);
9970     };
9971     eventBus._on("pagerender", onBeforeDraw, {
9972       signal
9973     });
9974     const onAfterDraw = evt => {
9975       if (evt.cssTransform) {
9976         return;
9977       }
9978       this._onePageRenderedCapability.resolve({
9979         timestamp: evt.timestamp
9980       });
9981       eventBus._off("pagerendered", onAfterDraw);
9982     };
9983     eventBus._on("pagerendered", onAfterDraw, {
9984       signal
9985     });
9986     Promise.all([firstPagePromise, permissionsPromise]).then(([firstPdfPage, permissions]) => {
9987       if (pdfDocument !== this.pdfDocument) {
9988         return;
9989       }
9990       this._firstPageCapability.resolve(firstPdfPage);
9991       this._optionalContentConfigPromise = optionalContentConfigPromise;
9992       const {
9993         annotationEditorMode,
9994         annotationMode,
9995         textLayerMode
9996       } = this.#initializePermissions(permissions);
9997       if (textLayerMode !== TextLayerMode.DISABLE) {
9998         const element = this.#hiddenCopyElement = document.createElement("div");
9999         element.id = "hiddenCopyElement";
10000         viewer.before(element);
10001       }
10002       if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
10003         const mode = annotationEditorMode;
10004         if (pdfDocument.isPureXfa) {
10005           console.warn("Warning: XFA-editing is not implemented.");
10006         } else if (isValidAnnotationEditorMode(mode)) {
10007           this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, viewer, this.#altTextManager, eventBus, pdfDocument, pageColors, this.#annotationEditorHighlightColors, this.#enableHighlightFloatingButton, this.#enableUpdatedAddImage, this.#enableNewAltTextWhenAddingImage, this.#mlManager, this.#editorUndoBar, this.#supportsPinchToZoom);
10008           eventBus.dispatch("annotationeditoruimanager", {
10009             source: this,
10010             uiManager: this.#annotationEditorUIManager
10011           });
10012           if (mode !== AnnotationEditorType.NONE) {
10013             if (mode === AnnotationEditorType.STAMP) {
10014               this.#mlManager?.loadModel("altText");
10015             }
10016             this.#annotationEditorUIManager.updateMode(mode);
10017           }
10018         } else {
10019           console.error(`Invalid AnnotationEditor mode: ${mode}`);
10020         }
10021       }
10022       const viewerElement = this._scrollMode === ScrollMode.PAGE ? null : viewer;
10023       const scale = this.currentScale;
10024       const viewport = firstPdfPage.getViewport({
10025         scale: scale * PixelsPerInch.PDF_TO_CSS_UNITS
10026       });
10027       viewer.style.setProperty("--scale-factor", viewport.scale);
10028       if (pageColors?.background) {
10029         viewer.style.setProperty("--page-bg-color", pageColors.background);
10030       }
10031       if (pageColors?.foreground === "CanvasText" || pageColors?.background === "Canvas") {
10032         viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight"));
10033         viewer.style.setProperty("--hcm-highlight-selected-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "ButtonText"));
10034       }
10035       for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
10036         const pageView = new PDFPageView({
10037           container: viewerElement,
10038           eventBus,
10039           id: pageNum,
10040           scale,
10041           defaultViewport: viewport.clone(),
10042           optionalContentConfigPromise,
10043           renderingQueue: this.renderingQueue,
10044           textLayerMode,
10045           annotationMode,
10046           imageResourcesPath: this.imageResourcesPath,
10047           maxCanvasPixels: this.maxCanvasPixels,
10048           pageColors,
10049           l10n: this.l10n,
10050           layerProperties: this._layerProperties,
10051           enableHWA: this.#enableHWA
10052         });
10053         this._pages.push(pageView);
10054       }
10055       this._pages[0]?.setPdfPage(firstPdfPage);
10056       if (this._scrollMode === ScrollMode.PAGE) {
10057         this.#ensurePageViewVisible();
10058       } else if (this._spreadMode !== SpreadMode.NONE) {
10059         this._updateSpreadMode();
10060       }
10061       this.#onePageRenderedOrForceFetch(signal).then(async () => {
10062         if (pdfDocument !== this.pdfDocument) {
10063           return;
10064         }
10065         this.findController?.setDocument(pdfDocument);
10066         this._scriptingManager?.setDocument(pdfDocument);
10067         if (this.#hiddenCopyElement) {
10068           document.addEventListener("copy", this.#copyCallback.bind(this, textLayerMode), {
10069             signal
10070           });
10071         }
10072         if (this.#annotationEditorUIManager) {
10073           eventBus.dispatch("annotationeditormodechanged", {
10074             source: this,
10075             mode: this.#annotationEditorMode
10076           });
10077         }
10078         if (pdfDocument.loadingParams.disableAutoFetch || pagesCount > PagesCountLimit.FORCE_LAZY_PAGE_INIT) {
10079           this._pagesCapability.resolve();
10080           return;
10081         }
10082         let getPagesLeft = pagesCount - 1;
10083         if (getPagesLeft <= 0) {
10084           this._pagesCapability.resolve();
10085           return;
10086         }
10087         for (let pageNum = 2; pageNum <= pagesCount; ++pageNum) {
10088           const promise = pdfDocument.getPage(pageNum).then(pdfPage => {
10089             const pageView = this._pages[pageNum - 1];
10090             if (!pageView.pdfPage) {
10091               pageView.setPdfPage(pdfPage);
10092             }
10093             if (--getPagesLeft === 0) {
10094               this._pagesCapability.resolve();
10095             }
10096           }, reason => {
10097             console.error(`Unable to get page ${pageNum} to initialize viewer`, reason);
10098             if (--getPagesLeft === 0) {
10099               this._pagesCapability.resolve();
10100             }
10101           });
10102           if (pageNum % PagesCountLimit.PAUSE_EAGER_PAGE_INIT === 0) {
10103             await promise;
10104           }
10105         }
10106       });
10107       eventBus.dispatch("pagesinit", {
10108         source: this
10109       });
10110       pdfDocument.getMetadata().then(({
10111         info
10112       }) => {
10113         if (pdfDocument !== this.pdfDocument) {
10114           return;
10115         }
10116         if (info.Language) {
10117           viewer.lang = info.Language;
10118         }
10119       });
10120       if (this.defaultRenderingQueue) {
10121         this.update();
10122       }
10123     }).catch(reason => {
10124       console.error("Unable to initialize viewer", reason);
10125       this._pagesCapability.reject(reason);
10126     });
10127   }
10128   setPageLabels(labels) {
10129     if (!this.pdfDocument) {
10130       return;
10131     }
10132     if (!labels) {
10133       this._pageLabels = null;
10134     } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {
10135       this._pageLabels = null;
10136       console.error(`setPageLabels: Invalid page labels.`);
10137     } else {
10138       this._pageLabels = labels;
10139     }
10140     for (let i = 0, ii = this._pages.length; i < ii; i++) {
10141       this._pages[i].setPageLabel(this._pageLabels?.[i] ?? null);
10142     }
10143   }
10144   _resetView() {
10145     this._pages = [];
10146     this._currentPageNumber = 1;
10147     this._currentScale = UNKNOWN_SCALE;
10148     this._currentScaleValue = null;
10149     this._pageLabels = null;
10150     this.#buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE);
10151     this._location = null;
10152     this._pagesRotation = 0;
10153     this._optionalContentConfigPromise = null;
10154     this._firstPageCapability = Promise.withResolvers();
10155     this._onePageRenderedCapability = Promise.withResolvers();
10156     this._pagesCapability = Promise.withResolvers();
10157     this._scrollMode = ScrollMode.VERTICAL;
10158     this._previousScrollMode = ScrollMode.UNKNOWN;
10159     this._spreadMode = SpreadMode.NONE;
10160     this.#scrollModePageState = {
10161       previousPageNumber: 1,
10162       scrollDown: true,
10163       pages: []
10164     };
10165     this.#eventAbortController?.abort();
10166     this.#eventAbortController = null;
10167     this.viewer.textContent = "";
10168     this._updateScrollMode();
10169     this.viewer.removeAttribute("lang");
10170     this.#hiddenCopyElement?.remove();
10171     this.#hiddenCopyElement = null;
10172     this.#cleanupSwitchAnnotationEditorMode();
10173   }
10174   #ensurePageViewVisible() {
10175     if (this._scrollMode !== ScrollMode.PAGE) {
10176       throw new Error("#ensurePageViewVisible: Invalid scrollMode value.");
10177     }
10178     const pageNumber = this._currentPageNumber,
10179       state = this.#scrollModePageState,
10180       viewer = this.viewer;
10181     viewer.textContent = "";
10182     state.pages.length = 0;
10183     if (this._spreadMode === SpreadMode.NONE && !this.isInPresentationMode) {
10184       const pageView = this._pages[pageNumber - 1];
10185       viewer.append(pageView.div);
10186       state.pages.push(pageView);
10187     } else {
10188       const pageIndexSet = new Set(),
10189         parity = this._spreadMode - 1;
10190       if (parity === -1) {
10191         pageIndexSet.add(pageNumber - 1);
10192       } else if (pageNumber % 2 !== parity) {
10193         pageIndexSet.add(pageNumber - 1);
10194         pageIndexSet.add(pageNumber);
10195       } else {
10196         pageIndexSet.add(pageNumber - 2);
10197         pageIndexSet.add(pageNumber - 1);
10198       }
10199       const spread = document.createElement("div");
10200       spread.className = "spread";
10201       if (this.isInPresentationMode) {
10202         const dummyPage = document.createElement("div");
10203         dummyPage.className = "dummyPage";
10204         spread.append(dummyPage);
10205       }
10206       for (const i of pageIndexSet) {
10207         const pageView = this._pages[i];
10208         if (!pageView) {
10209           continue;
10210         }
10211         spread.append(pageView.div);
10212         state.pages.push(pageView);
10213       }
10214       viewer.append(spread);
10215     }
10216     state.scrollDown = pageNumber >= state.previousPageNumber;
10217     state.previousPageNumber = pageNumber;
10218   }
10219   _scrollUpdate() {
10220     if (this.pagesCount === 0) {
10221       return;
10222     }
10223     this.update();
10224   }
10225   #scrollIntoView(pageView, pageSpot = null) {
10226     const {
10227       div,
10228       id
10229     } = pageView;
10230     if (this._currentPageNumber !== id) {
10231       this._setCurrentPageNumber(id);
10232     }
10233     if (this._scrollMode === ScrollMode.PAGE) {
10234       this.#ensurePageViewVisible();
10235       this.update();
10236     }
10237     if (!pageSpot && !this.isInPresentationMode) {
10238       const left = div.offsetLeft + div.clientLeft,
10239         right = left + div.clientWidth;
10240       const {
10241         scrollLeft,
10242         clientWidth
10243       } = this.container;
10244       if (this._scrollMode === ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) {
10245         pageSpot = {
10246           left: 0,
10247           top: 0
10248         };
10249       }
10250     }
10251     scrollIntoView(div, pageSpot);
10252     if (!this._currentScaleValue && this._location) {
10253       this._location = null;
10254     }
10255   }
10256   #isSameScale(newScale) {
10257     return newScale === this._currentScale || Math.abs(newScale - this._currentScale) < 1e-15;
10258   }
10259   #setScaleUpdatePages(newScale, newValue, {
10260     noScroll = false,
10261     preset = false,
10262     drawingDelay = -1,
10263     origin = null
10264   }) {
10265     this._currentScaleValue = newValue.toString();
10266     if (this.#isSameScale(newScale)) {
10267       if (preset) {
10268         this.eventBus.dispatch("scalechanging", {
10269           source: this,
10270           scale: newScale,
10271           presetValue: newValue
10272         });
10273       }
10274       return;
10275     }
10276     this.viewer.style.setProperty("--scale-factor", newScale * PixelsPerInch.PDF_TO_CSS_UNITS);
10277     const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
10278     this.refresh(true, {
10279       scale: newScale,
10280       drawingDelay: postponeDrawing ? drawingDelay : -1
10281     });
10282     if (postponeDrawing) {
10283       this.#scaleTimeoutId = setTimeout(() => {
10284         this.#scaleTimeoutId = null;
10285         this.refresh();
10286       }, drawingDelay);
10287     }
10288     const previousScale = this._currentScale;
10289     this._currentScale = newScale;
10290     if (!noScroll) {
10291       let page = this._currentPageNumber,
10292         dest;
10293       if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) {
10294         page = this._location.pageNumber;
10295         dest = [null, {
10296           name: "XYZ"
10297         }, this._location.left, this._location.top, null];
10298       }
10299       this.scrollPageIntoView({
10300         pageNumber: page,
10301         destArray: dest,
10302         allowNegativeOffset: true
10303       });
10304       if (Array.isArray(origin)) {
10305         const scaleDiff = newScale / previousScale - 1;
10306         const [top, left] = this.containerTopLeft;
10307         this.container.scrollLeft += (origin[0] - left) * scaleDiff;
10308         this.container.scrollTop += (origin[1] - top) * scaleDiff;
10309       }
10310     }
10311     this.eventBus.dispatch("scalechanging", {
10312       source: this,
10313       scale: newScale,
10314       presetValue: preset ? newValue : undefined
10315     });
10316     if (this.defaultRenderingQueue) {
10317       this.update();
10318     }
10319   }
10320   get #pageWidthScaleFactor() {
10321     if (this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL) {
10322       return 2;
10323     }
10324     return 1;
10325   }
10326   #setScale(value, options) {
10327     let scale = parseFloat(value);
10328     if (scale > 0) {
10329       options.preset = false;
10330       this.#setScaleUpdatePages(scale, value, options);
10331     } else {
10332       const currentPage = this._pages[this._currentPageNumber - 1];
10333       if (!currentPage) {
10334         return;
10335       }
10336       let hPadding = SCROLLBAR_PADDING,
10337         vPadding = VERTICAL_PADDING;
10338       if (this.isInPresentationMode) {
10339         hPadding = vPadding = 4;
10340         if (this._spreadMode !== SpreadMode.NONE) {
10341           hPadding *= 2;
10342         }
10343       } else if (this._scrollMode === ScrollMode.HORIZONTAL) {
10344         [hPadding, vPadding] = [vPadding, hPadding];
10345       }
10346       const pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale / this.#pageWidthScaleFactor;
10347       const pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale;
10348       switch (value) {
10349         case "page-actual":
10350           scale = 1;
10351           break;
10352         case "page-width":
10353           scale = pageWidthScale;
10354           break;
10355         case "page-height":
10356           scale = pageHeightScale;
10357           break;
10358         case "page-fit":
10359           scale = Math.min(pageWidthScale, pageHeightScale);
10360           break;
10361         case "auto":
10362           const horizontalScale = isPortraitOrientation(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale);
10363           scale = Math.min(MAX_AUTO_SCALE, horizontalScale);
10364           break;
10365         default:
10366           console.error(`#setScale: "${value}" is an unknown zoom value.`);
10367           return;
10368       }
10369       options.preset = true;
10370       this.#setScaleUpdatePages(scale, value, options);
10371     }
10372   }
10373   #resetCurrentPageView() {
10374     const pageView = this._pages[this._currentPageNumber - 1];
10375     if (this.isInPresentationMode) {
10376       this.#setScale(this._currentScaleValue, {
10377         noScroll: true
10378       });
10379     }
10380     this.#scrollIntoView(pageView);
10381   }
10382   pageLabelToPageNumber(label) {
10383     if (!this._pageLabels) {
10384       return null;
10385     }
10386     const i = this._pageLabels.indexOf(label);
10387     if (i < 0) {
10388       return null;
10389     }
10390     return i + 1;
10391   }
10392   scrollPageIntoView({
10393     pageNumber,
10394     destArray = null,
10395     allowNegativeOffset = false,
10396     ignoreDestinationZoom = false
10397   }) {
10398     if (!this.pdfDocument) {
10399       return;
10400     }
10401     const pageView = Number.isInteger(pageNumber) && this._pages[pageNumber - 1];
10402     if (!pageView) {
10403       console.error(`scrollPageIntoView: "${pageNumber}" is not a valid pageNumber parameter.`);
10404       return;
10405     }
10406     if (this.isInPresentationMode || !destArray) {
10407       this._setCurrentPageNumber(pageNumber, true);
10408       return;
10409     }
10410     let x = 0,
10411       y = 0;
10412     let width = 0,
10413       height = 0,
10414       widthScale,
10415       heightScale;
10416     const changeOrientation = pageView.rotation % 180 !== 0;
10417     const pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS;
10418     const pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS;
10419     let scale = 0;
10420     switch (destArray[1].name) {
10421       case "XYZ":
10422         x = destArray[2];
10423         y = destArray[3];
10424         scale = destArray[4];
10425         x = x !== null ? x : 0;
10426         y = y !== null ? y : pageHeight;
10427         break;
10428       case "Fit":
10429       case "FitB":
10430         scale = "page-fit";
10431         break;
10432       case "FitH":
10433       case "FitBH":
10434         y = destArray[2];
10435         scale = "page-width";
10436         if (y === null && this._location) {
10437           x = this._location.left;
10438           y = this._location.top;
10439         } else if (typeof y !== "number" || y < 0) {
10440           y = pageHeight;
10441         }
10442         break;
10443       case "FitV":
10444       case "FitBV":
10445         x = destArray[2];
10446         width = pageWidth;
10447         height = pageHeight;
10448         scale = "page-height";
10449         break;
10450       case "FitR":
10451         x = destArray[2];
10452         y = destArray[3];
10453         width = destArray[4] - x;
10454         height = destArray[5] - y;
10455         let hPadding = SCROLLBAR_PADDING,
10456           vPadding = VERTICAL_PADDING;
10457         widthScale = (this.container.clientWidth - hPadding) / width / PixelsPerInch.PDF_TO_CSS_UNITS;
10458         heightScale = (this.container.clientHeight - vPadding) / height / PixelsPerInch.PDF_TO_CSS_UNITS;
10459         scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
10460         break;
10461       default:
10462         console.error(`scrollPageIntoView: "${destArray[1].name}" is not a valid destination type.`);
10463         return;
10464     }
10465     if (!ignoreDestinationZoom) {
10466       if (scale && scale !== this._currentScale) {
10467         this.currentScaleValue = scale;
10468       } else if (this._currentScale === UNKNOWN_SCALE) {
10469         this.currentScaleValue = DEFAULT_SCALE_VALUE;
10470       }
10471     }
10472     if (scale === "page-fit" && !destArray[4]) {
10473       this.#scrollIntoView(pageView);
10474       return;
10475     }
10476     const boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)];
10477     let left = Math.min(boundingRect[0][0], boundingRect[1][0]);
10478     let top = Math.min(boundingRect[0][1], boundingRect[1][1]);
10479     if (!allowNegativeOffset) {
10480       left = Math.max(left, 0);
10481       top = Math.max(top, 0);
10482     }
10483     this.#scrollIntoView(pageView, {
10484       left,
10485       top
10486     });
10487   }
10488   _updateLocation(firstPage) {
10489     const currentScale = this._currentScale;
10490     const currentScaleValue = this._currentScaleValue;
10491     const normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue;
10492     const pageNumber = firstPage.id;
10493     const currentPageView = this._pages[pageNumber - 1];
10494     const container = this.container;
10495     const topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y);
10496     const intLeft = Math.round(topLeft[0]);
10497     const intTop = Math.round(topLeft[1]);
10498     let pdfOpenParams = `#page=${pageNumber}`;
10499     if (!this.isInPresentationMode) {
10500       pdfOpenParams += `&zoom=${normalizedScaleValue},${intLeft},${intTop}`;
10501     }
10502     this._location = {
10503       pageNumber,
10504       scale: normalizedScaleValue,
10505       top: intTop,
10506       left: intLeft,
10507       rotation: this._pagesRotation,
10508       pdfOpenParams
10509     };
10510   }
10511   update() {
10512     const visible = this._getVisiblePages();
10513     const visiblePages = visible.views,
10514       numVisiblePages = visiblePages.length;
10515     if (numVisiblePages === 0) {
10516       return;
10517     }
10518     const newCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1);
10519     this.#buffer.resize(newCacheSize, visible.ids);
10520     this.renderingQueue.renderHighestPriority(visible);
10521     const isSimpleLayout = this._spreadMode === SpreadMode.NONE && (this._scrollMode === ScrollMode.PAGE || this._scrollMode === ScrollMode.VERTICAL);
10522     const currentId = this._currentPageNumber;
10523     let stillFullyVisible = false;
10524     for (const page of visiblePages) {
10525       if (page.percent < 100) {
10526         break;
10527       }
10528       if (page.id === currentId && isSimpleLayout) {
10529         stillFullyVisible = true;
10530         break;
10531       }
10532     }
10533     this._setCurrentPageNumber(stillFullyVisible ? currentId : visiblePages[0].id);
10534     this._updateLocation(visible.first);
10535     this.eventBus.dispatch("updateviewarea", {
10536       source: this,
10537       location: this._location
10538     });
10539   }
10540   #switchToEditAnnotationMode() {
10541     const visible = this._getVisiblePages();
10542     const pagesToRefresh = [];
10543     const {
10544       ids,
10545       views
10546     } = visible;
10547     for (const page of views) {
10548       const {
10549         view
10550       } = page;
10551       if (!view.hasEditableAnnotations()) {
10552         ids.delete(view.id);
10553         continue;
10554       }
10555       pagesToRefresh.push(page);
10556     }
10557     if (pagesToRefresh.length === 0) {
10558       return null;
10559     }
10560     this.renderingQueue.renderHighestPriority({
10561       first: pagesToRefresh[0],
10562       last: pagesToRefresh.at(-1),
10563       views: pagesToRefresh,
10564       ids
10565     });
10566     return ids;
10567   }
10568   containsElement(element) {
10569     return this.container.contains(element);
10570   }
10571   focus() {
10572     this.container.focus();
10573   }
10574   get _isContainerRtl() {
10575     return getComputedStyle(this.container).direction === "rtl";
10576   }
10577   get isInPresentationMode() {
10578     return this.presentationModeState === PresentationModeState.FULLSCREEN;
10579   }
10580   get isChangingPresentationMode() {
10581     return this.presentationModeState === PresentationModeState.CHANGING;
10582   }
10583   get isHorizontalScrollbarEnabled() {
10584     return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth;
10585   }
10586   get isVerticalScrollbarEnabled() {
10587     return this.isInPresentationMode ? false : this.container.scrollHeight > this.container.clientHeight;
10588   }
10589   _getVisiblePages() {
10590     const views = this._scrollMode === ScrollMode.PAGE ? this.#scrollModePageState.pages : this._pages,
10591       horizontal = this._scrollMode === ScrollMode.HORIZONTAL,
10592       rtl = horizontal && this._isContainerRtl;
10593     return getVisibleElements({
10594       scrollEl: this.container,
10595       views,
10596       sortByVisibility: true,
10597       horizontal,
10598       rtl
10599     });
10600   }
10601   cleanup() {
10602     for (const pageView of this._pages) {
10603       if (pageView.renderingState !== RenderingStates.FINISHED) {
10604         pageView.reset();
10605       }
10606     }
10607   }
10608   _cancelRendering() {
10609     for (const pageView of this._pages) {
10610       pageView.cancelRendering();
10611     }
10612   }
10613   async #ensurePdfPageLoaded(pageView) {
10614     if (pageView.pdfPage) {
10615       return pageView.pdfPage;
10616     }
10617     try {
10618       const pdfPage = await this.pdfDocument.getPage(pageView.id);
10619       if (!pageView.pdfPage) {
10620         pageView.setPdfPage(pdfPage);
10621       }
10622       return pdfPage;
10623     } catch (reason) {
10624       console.error("Unable to get page for page view", reason);
10625       return null;
10626     }
10627   }
10628   #getScrollAhead(visible) {
10629     if (visible.first?.id === 1) {
10630       return true;
10631     } else if (visible.last?.id === this.pagesCount) {
10632       return false;
10633     }
10634     switch (this._scrollMode) {
10635       case ScrollMode.PAGE:
10636         return this.#scrollModePageState.scrollDown;
10637       case ScrollMode.HORIZONTAL:
10638         return this.scroll.right;
10639     }
10640     return this.scroll.down;
10641   }
10642   forceRendering(currentlyVisiblePages) {
10643     const visiblePages = currentlyVisiblePages || this._getVisiblePages();
10644     const scrollAhead = this.#getScrollAhead(visiblePages);
10645     const preRenderExtra = this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL;
10646     const pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead, preRenderExtra);
10647     if (pageView) {
10648       this.#ensurePdfPageLoaded(pageView).then(() => {
10649         this.renderingQueue.renderView(pageView);
10650       });
10651       return true;
10652     }
10653     return false;
10654   }
10655   get hasEqualPageSizes() {
10656     const firstPageView = this._pages[0];
10657     for (let i = 1, ii = this._pages.length; i < ii; ++i) {
10658       const pageView = this._pages[i];
10659       if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) {
10660         return false;
10661       }
10662     }
10663     return true;
10664   }
10665   getPagesOverview() {
10666     let initialOrientation;
10667     return this._pages.map(pageView => {
10668       const viewport = pageView.pdfPage.getViewport({
10669         scale: 1
10670       });
10671       const orientation = isPortraitOrientation(viewport);
10672       if (initialOrientation === undefined) {
10673         initialOrientation = orientation;
10674       } else if (this.enablePrintAutoRotate && orientation !== initialOrientation) {
10675         return {
10676           width: viewport.height,
10677           height: viewport.width,
10678           rotation: (viewport.rotation - 90) % 360
10679         };
10680       }
10681       return {
10682         width: viewport.width,
10683         height: viewport.height,
10684         rotation: viewport.rotation
10685       };
10686     });
10687   }
10688   get optionalContentConfigPromise() {
10689     if (!this.pdfDocument) {
10690       return Promise.resolve(null);
10691     }
10692     if (!this._optionalContentConfigPromise) {
10693       console.error("optionalContentConfigPromise: Not initialized yet.");
10694       return this.pdfDocument.getOptionalContentConfig({
10695         intent: "display"
10696       });
10697     }
10698     return this._optionalContentConfigPromise;
10699   }
10700   set optionalContentConfigPromise(promise) {
10701     if (!(promise instanceof Promise)) {
10702       throw new Error(`Invalid optionalContentConfigPromise: ${promise}`);
10703     }
10704     if (!this.pdfDocument) {
10705       return;
10706     }
10707     if (!this._optionalContentConfigPromise) {
10708       return;
10709     }
10710     this._optionalContentConfigPromise = promise;
10711     this.refresh(false, {
10712       optionalContentConfigPromise: promise
10713     });
10714     this.eventBus.dispatch("optionalcontentconfigchanged", {
10715       source: this,
10716       promise
10717     });
10718   }
10719   get scrollMode() {
10720     return this._scrollMode;
10721   }
10722   set scrollMode(mode) {
10723     if (this._scrollMode === mode) {
10724       return;
10725     }
10726     if (!isValidScrollMode(mode)) {
10727       throw new Error(`Invalid scroll mode: ${mode}`);
10728     }
10729     if (this.pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {
10730       return;
10731     }
10732     this._previousScrollMode = this._scrollMode;
10733     this._scrollMode = mode;
10734     this.eventBus.dispatch("scrollmodechanged", {
10735       source: this,
10736       mode
10737     });
10738     this._updateScrollMode(this._currentPageNumber);
10739   }
10740   _updateScrollMode(pageNumber = null) {
10741     const scrollMode = this._scrollMode,
10742       viewer = this.viewer;
10743     viewer.classList.toggle("scrollHorizontal", scrollMode === ScrollMode.HORIZONTAL);
10744     viewer.classList.toggle("scrollWrapped", scrollMode === ScrollMode.WRAPPED);
10745     if (!this.pdfDocument || !pageNumber) {
10746       return;
10747     }
10748     if (scrollMode === ScrollMode.PAGE) {
10749       this.#ensurePageViewVisible();
10750     } else if (this._previousScrollMode === ScrollMode.PAGE) {
10751       this._updateSpreadMode();
10752     }
10753     if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
10754       this.#setScale(this._currentScaleValue, {
10755         noScroll: true
10756       });
10757     }
10758     this._setCurrentPageNumber(pageNumber, true);
10759     this.update();
10760   }
10761   get spreadMode() {
10762     return this._spreadMode;
10763   }
10764   set spreadMode(mode) {
10765     if (this._spreadMode === mode) {
10766       return;
10767     }
10768     if (!isValidSpreadMode(mode)) {
10769       throw new Error(`Invalid spread mode: ${mode}`);
10770     }
10771     this._spreadMode = mode;
10772     this.eventBus.dispatch("spreadmodechanged", {
10773       source: this,
10774       mode
10775     });
10776     this._updateSpreadMode(this._currentPageNumber);
10777   }
10778   _updateSpreadMode(pageNumber = null) {
10779     if (!this.pdfDocument) {
10780       return;
10781     }
10782     const viewer = this.viewer,
10783       pages = this._pages;
10784     if (this._scrollMode === ScrollMode.PAGE) {
10785       this.#ensurePageViewVisible();
10786     } else {
10787       viewer.textContent = "";
10788       if (this._spreadMode === SpreadMode.NONE) {
10789         for (const pageView of this._pages) {
10790           viewer.append(pageView.div);
10791         }
10792       } else {
10793         const parity = this._spreadMode - 1;
10794         let spread = null;
10795         for (let i = 0, ii = pages.length; i < ii; ++i) {
10796           if (spread === null) {
10797             spread = document.createElement("div");
10798             spread.className = "spread";
10799             viewer.append(spread);
10800           } else if (i % 2 === parity) {
10801             spread = spread.cloneNode(false);
10802             viewer.append(spread);
10803           }
10804           spread.append(pages[i].div);
10805         }
10806       }
10807     }
10808     if (!pageNumber) {
10809       return;
10810     }
10811     if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
10812       this.#setScale(this._currentScaleValue, {
10813         noScroll: true
10814       });
10815     }
10816     this._setCurrentPageNumber(pageNumber, true);
10817     this.update();
10818   }
10819   _getPageAdvance(currentPageNumber, previous = false) {
10820     switch (this._scrollMode) {
10821       case ScrollMode.WRAPPED:
10822         {
10823           const {
10824               views
10825             } = this._getVisiblePages(),
10826             pageLayout = new Map();
10827           for (const {
10828             id,
10829             y,
10830             percent,
10831             widthPercent
10832           } of views) {
10833             if (percent === 0 || widthPercent < 100) {
10834               continue;
10835             }
10836             let yArray = pageLayout.get(y);
10837             if (!yArray) {
10838               pageLayout.set(y, yArray ||= []);
10839             }
10840             yArray.push(id);
10841           }
10842           for (const yArray of pageLayout.values()) {
10843             const currentIndex = yArray.indexOf(currentPageNumber);
10844             if (currentIndex === -1) {
10845               continue;
10846             }
10847             const numPages = yArray.length;
10848             if (numPages === 1) {
10849               break;
10850             }
10851             if (previous) {
10852               for (let i = currentIndex - 1, ii = 0; i >= ii; i--) {
10853                 const currentId = yArray[i],
10854                   expectedId = yArray[i + 1] - 1;
10855                 if (currentId < expectedId) {
10856                   return currentPageNumber - expectedId;
10857                 }
10858               }
10859             } else {
10860               for (let i = currentIndex + 1, ii = numPages; i < ii; i++) {
10861                 const currentId = yArray[i],
10862                   expectedId = yArray[i - 1] + 1;
10863                 if (currentId > expectedId) {
10864                   return expectedId - currentPageNumber;
10865                 }
10866               }
10867             }
10868             if (previous) {
10869               const firstId = yArray[0];
10870               if (firstId < currentPageNumber) {
10871                 return currentPageNumber - firstId + 1;
10872               }
10873             } else {
10874               const lastId = yArray[numPages - 1];
10875               if (lastId > currentPageNumber) {
10876                 return lastId - currentPageNumber + 1;
10877               }
10878             }
10879             break;
10880           }
10881           break;
10882         }
10883       case ScrollMode.HORIZONTAL:
10884         {
10885           break;
10886         }
10887       case ScrollMode.PAGE:
10888       case ScrollMode.VERTICAL:
10889         {
10890           if (this._spreadMode === SpreadMode.NONE) {
10891             break;
10892           }
10893           const parity = this._spreadMode - 1;
10894           if (previous && currentPageNumber % 2 !== parity) {
10895             break;
10896           } else if (!previous && currentPageNumber % 2 === parity) {
10897             break;
10898           }
10899           const {
10900               views
10901             } = this._getVisiblePages(),
10902             expectedId = previous ? currentPageNumber - 1 : currentPageNumber + 1;
10903           for (const {
10904             id,
10905             percent,
10906             widthPercent
10907           } of views) {
10908             if (id !== expectedId) {
10909               continue;
10910             }
10911             if (percent > 0 && widthPercent === 100) {
10912               return 2;
10913             }
10914             break;
10915           }
10916           break;
10917         }
10918     }
10919     return 1;
10920   }
10921   nextPage() {
10922     const currentPageNumber = this._currentPageNumber,
10923       pagesCount = this.pagesCount;
10924     if (currentPageNumber >= pagesCount) {
10925       return false;
10926     }
10927     const advance = this._getPageAdvance(currentPageNumber, false) || 1;
10928     this.currentPageNumber = Math.min(currentPageNumber + advance, pagesCount);
10929     return true;
10930   }
10931   previousPage() {
10932     const currentPageNumber = this._currentPageNumber;
10933     if (currentPageNumber <= 1) {
10934       return false;
10935     }
10936     const advance = this._getPageAdvance(currentPageNumber, true) || 1;
10937     this.currentPageNumber = Math.max(currentPageNumber - advance, 1);
10938     return true;
10939   }
10940   updateScale({
10941     drawingDelay,
10942     scaleFactor = null,
10943     steps = null,
10944     origin
10945   }) {
10946     if (steps === null && scaleFactor === null) {
10947       throw new Error("Invalid updateScale options: either `steps` or `scaleFactor` must be provided.");
10948     }
10949     if (!this.pdfDocument) {
10950       return;
10951     }
10952     let newScale = this._currentScale;
10953     if (scaleFactor > 0 && scaleFactor !== 1) {
10954       newScale = Math.round(newScale * scaleFactor * 100) / 100;
10955     } else if (steps) {
10956       const delta = steps > 0 ? DEFAULT_SCALE_DELTA : 1 / DEFAULT_SCALE_DELTA;
10957       const round = steps > 0 ? Math.ceil : Math.floor;
10958       steps = Math.abs(steps);
10959       do {
10960         newScale = round((newScale * delta).toFixed(2) * 10) / 10;
10961       } while (--steps > 0);
10962     }
10963     newScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, newScale));
10964     this.#setScale(newScale, {
10965       noScroll: false,
10966       drawingDelay,
10967       origin
10968     });
10969   }
10970   increaseScale(options = {}) {
10971     this.updateScale({
10972       ...options,
10973       steps: options.steps ?? 1
10974     });
10975   }
10976   decreaseScale(options = {}) {
10977     this.updateScale({
10978       ...options,
10979       steps: -(options.steps ?? 1)
10980     });
10981   }
10982   #updateContainerHeightCss(height = this.container.clientHeight) {
10983     if (height !== this.#previousContainerHeight) {
10984       this.#previousContainerHeight = height;
10985       docStyle.setProperty("--viewer-container-height", `${height}px`);
10986     }
10987   }
10988   #resizeObserverCallback(entries) {
10989     for (const entry of entries) {
10990       if (entry.target === this.container) {
10991         this.#updateContainerHeightCss(Math.floor(entry.borderBoxSize[0].blockSize));
10992         this.#containerTopLeft = null;
10993         break;
10994       }
10995     }
10996   }
10997   get containerTopLeft() {
10998     return this.#containerTopLeft ||= [this.container.offsetTop, this.container.offsetLeft];
10999   }
11000   #cleanupSwitchAnnotationEditorMode() {
11001     this.#switchAnnotationEditorModeAC?.abort();
11002     this.#switchAnnotationEditorModeAC = null;
11003     if (this.#switchAnnotationEditorModeTimeoutId !== null) {
11004       clearTimeout(this.#switchAnnotationEditorModeTimeoutId);
11005       this.#switchAnnotationEditorModeTimeoutId = null;
11006     }
11007   }
11008   get annotationEditorMode() {
11009     return this.#annotationEditorUIManager ? this.#annotationEditorMode : AnnotationEditorType.DISABLE;
11010   }
11011   set annotationEditorMode({
11012     mode,
11013     editId = null,
11014     isFromKeyboard = false
11015   }) {
11016     if (!this.#annotationEditorUIManager) {
11017       throw new Error(`The AnnotationEditor is not enabled.`);
11018     }
11019     if (this.#annotationEditorMode === mode) {
11020       return;
11021     }
11022     if (!isValidAnnotationEditorMode(mode)) {
11023       throw new Error(`Invalid AnnotationEditor mode: ${mode}`);
11024     }
11025     if (!this.pdfDocument) {
11026       return;
11027     }
11028     if (mode === AnnotationEditorType.STAMP) {
11029       this.#mlManager?.loadModel("altText");
11030     }
11031     const {
11032       eventBus,
11033       pdfDocument
11034     } = this;
11035     const updater = async () => {
11036       this.#cleanupSwitchAnnotationEditorMode();
11037       this.#annotationEditorMode = mode;
11038       await this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard);
11039       if (mode !== this.#annotationEditorMode || pdfDocument !== this.pdfDocument) {
11040         return;
11041       }
11042       eventBus.dispatch("annotationeditormodechanged", {
11043         source: this,
11044         mode
11045       });
11046     };
11047     if (mode === AnnotationEditorType.NONE || this.#annotationEditorMode === AnnotationEditorType.NONE) {
11048       const isEditing = mode !== AnnotationEditorType.NONE;
11049       if (!isEditing) {
11050         this.pdfDocument.annotationStorage.resetModifiedIds();
11051       }
11052       for (const pageView of this._pages) {
11053         pageView.toggleEditingMode(isEditing);
11054       }
11055       const idsToRefresh = this.#switchToEditAnnotationMode();
11056       if (isEditing && idsToRefresh) {
11057         this.#cleanupSwitchAnnotationEditorMode();
11058         this.#switchAnnotationEditorModeAC = new AbortController();
11059         const signal = AbortSignal.any([this.#eventAbortController.signal, this.#switchAnnotationEditorModeAC.signal]);
11060         eventBus._on("pagerendered", ({
11061           pageNumber
11062         }) => {
11063           idsToRefresh.delete(pageNumber);
11064           if (idsToRefresh.size === 0) {
11065             this.#switchAnnotationEditorModeTimeoutId = setTimeout(updater, 0);
11066           }
11067         }, {
11068           signal
11069         });
11070         return;
11071       }
11072     }
11073     updater();
11074   }
11075   refresh(noUpdate = false, updateArgs = Object.create(null)) {
11076     if (!this.pdfDocument) {
11077       return;
11078     }
11079     for (const pageView of this._pages) {
11080       pageView.update(updateArgs);
11081     }
11082     if (this.#scaleTimeoutId !== null) {
11083       clearTimeout(this.#scaleTimeoutId);
11084       this.#scaleTimeoutId = null;
11085     }
11086     if (!noUpdate) {
11087       this.update();
11088     }
11089   }
11092 ;// ./web/secondary_toolbar.js
11095 class SecondaryToolbar {
11096   #opts;
11097   constructor(options, eventBus) {
11098     this.#opts = options;
11099     const buttons = [{
11100       element: options.presentationModeButton,
11101       eventName: "presentationmode",
11102       close: true
11103     }, {
11104       element: options.printButton,
11105       eventName: "print",
11106       close: true
11107     }, {
11108       element: options.downloadButton,
11109       eventName: "download",
11110       close: true
11111     }, {
11112       element: options.viewBookmarkButton,
11113       eventName: null,
11114       close: true
11115     }, {
11116       element: options.firstPageButton,
11117       eventName: "firstpage",
11118       close: true
11119     }, {
11120       element: options.lastPageButton,
11121       eventName: "lastpage",
11122       close: true
11123     }, {
11124       element: options.pageRotateCwButton,
11125       eventName: "rotatecw",
11126       close: false
11127     }, {
11128       element: options.pageRotateCcwButton,
11129       eventName: "rotateccw",
11130       close: false
11131     }, {
11132       element: options.cursorSelectToolButton,
11133       eventName: "switchcursortool",
11134       eventDetails: {
11135         tool: CursorTool.SELECT
11136       },
11137       close: true
11138     }, {
11139       element: options.cursorHandToolButton,
11140       eventName: "switchcursortool",
11141       eventDetails: {
11142         tool: CursorTool.HAND
11143       },
11144       close: true
11145     }, {
11146       element: options.scrollPageButton,
11147       eventName: "switchscrollmode",
11148       eventDetails: {
11149         mode: ScrollMode.PAGE
11150       },
11151       close: true
11152     }, {
11153       element: options.scrollVerticalButton,
11154       eventName: "switchscrollmode",
11155       eventDetails: {
11156         mode: ScrollMode.VERTICAL
11157       },
11158       close: true
11159     }, {
11160       element: options.scrollHorizontalButton,
11161       eventName: "switchscrollmode",
11162       eventDetails: {
11163         mode: ScrollMode.HORIZONTAL
11164       },
11165       close: true
11166     }, {
11167       element: options.scrollWrappedButton,
11168       eventName: "switchscrollmode",
11169       eventDetails: {
11170         mode: ScrollMode.WRAPPED
11171       },
11172       close: true
11173     }, {
11174       element: options.spreadNoneButton,
11175       eventName: "switchspreadmode",
11176       eventDetails: {
11177         mode: SpreadMode.NONE
11178       },
11179       close: true
11180     }, {
11181       element: options.spreadOddButton,
11182       eventName: "switchspreadmode",
11183       eventDetails: {
11184         mode: SpreadMode.ODD
11185       },
11186       close: true
11187     }, {
11188       element: options.spreadEvenButton,
11189       eventName: "switchspreadmode",
11190       eventDetails: {
11191         mode: SpreadMode.EVEN
11192       },
11193       close: true
11194     }, {
11195       element: options.imageAltTextSettingsButton,
11196       eventName: "imagealttextsettings",
11197       close: true
11198     }, {
11199       element: options.documentPropertiesButton,
11200       eventName: "documentproperties",
11201       close: true
11202     }];
11203     this.eventBus = eventBus;
11204     this.opened = false;
11205     this.#bindListeners(buttons);
11206     this.reset();
11207   }
11208   get isOpen() {
11209     return this.opened;
11210   }
11211   setPageNumber(pageNumber) {
11212     this.pageNumber = pageNumber;
11213     this.#updateUIState();
11214   }
11215   setPagesCount(pagesCount) {
11216     this.pagesCount = pagesCount;
11217     this.#updateUIState();
11218   }
11219   reset() {
11220     this.pageNumber = 0;
11221     this.pagesCount = 0;
11222     this.#updateUIState();
11223     this.eventBus.dispatch("switchcursortool", {
11224       source: this,
11225       reset: true
11226     });
11227     this.#scrollModeChanged({
11228       mode: ScrollMode.VERTICAL
11229     });
11230     this.#spreadModeChanged({
11231       mode: SpreadMode.NONE
11232     });
11233   }
11234   #updateUIState() {
11235     const {
11236       firstPageButton,
11237       lastPageButton,
11238       pageRotateCwButton,
11239       pageRotateCcwButton
11240     } = this.#opts;
11241     firstPageButton.disabled = this.pageNumber <= 1;
11242     lastPageButton.disabled = this.pageNumber >= this.pagesCount;
11243     pageRotateCwButton.disabled = this.pagesCount === 0;
11244     pageRotateCcwButton.disabled = this.pagesCount === 0;
11245   }
11246   #bindListeners(buttons) {
11247     const {
11248       eventBus
11249     } = this;
11250     const {
11251       toggleButton
11252     } = this.#opts;
11253     toggleButton.addEventListener("click", this.toggle.bind(this));
11254     for (const {
11255       element,
11256       eventName,
11257       close,
11258       eventDetails
11259     } of buttons) {
11260       element.addEventListener("click", evt => {
11261         if (eventName !== null) {
11262           eventBus.dispatch(eventName, {
11263             source: this,
11264             ...eventDetails
11265           });
11266         }
11267         if (close) {
11268           this.close();
11269         }
11270         eventBus.dispatch("reporttelemetry", {
11271           source: this,
11272           details: {
11273             type: "buttons",
11274             data: {
11275               id: element.id
11276             }
11277           }
11278         });
11279       });
11280     }
11281     eventBus._on("cursortoolchanged", this.#cursorToolChanged.bind(this));
11282     eventBus._on("scrollmodechanged", this.#scrollModeChanged.bind(this));
11283     eventBus._on("spreadmodechanged", this.#spreadModeChanged.bind(this));
11284   }
11285   #cursorToolChanged({
11286     tool,
11287     disabled
11288   }) {
11289     const {
11290       cursorSelectToolButton,
11291       cursorHandToolButton
11292     } = this.#opts;
11293     toggleCheckedBtn(cursorSelectToolButton, tool === CursorTool.SELECT);
11294     toggleCheckedBtn(cursorHandToolButton, tool === CursorTool.HAND);
11295     cursorSelectToolButton.disabled = disabled;
11296     cursorHandToolButton.disabled = disabled;
11297   }
11298   #scrollModeChanged({
11299     mode
11300   }) {
11301     const {
11302       scrollPageButton,
11303       scrollVerticalButton,
11304       scrollHorizontalButton,
11305       scrollWrappedButton,
11306       spreadNoneButton,
11307       spreadOddButton,
11308       spreadEvenButton
11309     } = this.#opts;
11310     toggleCheckedBtn(scrollPageButton, mode === ScrollMode.PAGE);
11311     toggleCheckedBtn(scrollVerticalButton, mode === ScrollMode.VERTICAL);
11312     toggleCheckedBtn(scrollHorizontalButton, mode === ScrollMode.HORIZONTAL);
11313     toggleCheckedBtn(scrollWrappedButton, mode === ScrollMode.WRAPPED);
11314     const forceScrollModePage = this.pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE;
11315     scrollPageButton.disabled = forceScrollModePage;
11316     scrollVerticalButton.disabled = forceScrollModePage;
11317     scrollHorizontalButton.disabled = forceScrollModePage;
11318     scrollWrappedButton.disabled = forceScrollModePage;
11319     const isHorizontal = mode === ScrollMode.HORIZONTAL;
11320     spreadNoneButton.disabled = isHorizontal;
11321     spreadOddButton.disabled = isHorizontal;
11322     spreadEvenButton.disabled = isHorizontal;
11323   }
11324   #spreadModeChanged({
11325     mode
11326   }) {
11327     const {
11328       spreadNoneButton,
11329       spreadOddButton,
11330       spreadEvenButton
11331     } = this.#opts;
11332     toggleCheckedBtn(spreadNoneButton, mode === SpreadMode.NONE);
11333     toggleCheckedBtn(spreadOddButton, mode === SpreadMode.ODD);
11334     toggleCheckedBtn(spreadEvenButton, mode === SpreadMode.EVEN);
11335   }
11336   open() {
11337     if (this.opened) {
11338       return;
11339     }
11340     this.opened = true;
11341     const {
11342       toggleButton,
11343       toolbar
11344     } = this.#opts;
11345     toggleExpandedBtn(toggleButton, true, toolbar);
11346   }
11347   close() {
11348     if (!this.opened) {
11349       return;
11350     }
11351     this.opened = false;
11352     const {
11353       toggleButton,
11354       toolbar
11355     } = this.#opts;
11356     toggleExpandedBtn(toggleButton, false, toolbar);
11357   }
11358   toggle() {
11359     if (this.opened) {
11360       this.close();
11361     } else {
11362       this.open();
11363     }
11364   }
11367 ;// ./web/toolbar.js
11370 class Toolbar {
11371   #colorPicker = null;
11372   #opts;
11373   constructor(options, eventBus, toolbarDensity = 0) {
11374     this.#opts = options;
11375     this.eventBus = eventBus;
11376     const buttons = [{
11377       element: options.previous,
11378       eventName: "previouspage"
11379     }, {
11380       element: options.next,
11381       eventName: "nextpage"
11382     }, {
11383       element: options.zoomIn,
11384       eventName: "zoomin"
11385     }, {
11386       element: options.zoomOut,
11387       eventName: "zoomout"
11388     }, {
11389       element: options.print,
11390       eventName: "print"
11391     }, {
11392       element: options.download,
11393       eventName: "download"
11394     }, {
11395       element: options.editorFreeTextButton,
11396       eventName: "switchannotationeditormode",
11397       eventDetails: {
11398         get mode() {
11399           const {
11400             classList
11401           } = options.editorFreeTextButton;
11402           return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.FREETEXT;
11403         }
11404       }
11405     }, {
11406       element: options.editorHighlightButton,
11407       eventName: "switchannotationeditormode",
11408       eventDetails: {
11409         get mode() {
11410           const {
11411             classList
11412           } = options.editorHighlightButton;
11413           return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.HIGHLIGHT;
11414         }
11415       }
11416     }, {
11417       element: options.editorInkButton,
11418       eventName: "switchannotationeditormode",
11419       eventDetails: {
11420         get mode() {
11421           const {
11422             classList
11423           } = options.editorInkButton;
11424           return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.INK;
11425         }
11426       }
11427     }, {
11428       element: options.editorStampButton,
11429       eventName: "switchannotationeditormode",
11430       eventDetails: {
11431         get mode() {
11432           const {
11433             classList
11434           } = options.editorStampButton;
11435           return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.STAMP;
11436         }
11437       },
11438       telemetry: {
11439         type: "editing",
11440         data: {
11441           action: "pdfjs.image.icon_click"
11442         }
11443       }
11444     }, {
11445       element: options.editorSignatureButton,
11446       eventName: "switchannotationeditormode",
11447       eventDetails: {
11448         get mode() {
11449           const {
11450             classList
11451           } = options.editorSignatureButton;
11452           return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.SIGNATURE;
11453         }
11454       }
11455     }];
11456     this.#bindListeners(buttons);
11457     this.#updateToolbarDensity({
11458       value: toolbarDensity
11459     });
11460     this.reset();
11461   }
11462   #updateToolbarDensity({
11463     value
11464   }) {
11465     let name = "normal";
11466     switch (value) {
11467       case 1:
11468         name = "compact";
11469         break;
11470       case 2:
11471         name = "touch";
11472         break;
11473     }
11474     document.documentElement.setAttribute("data-toolbar-density", name);
11475   }
11476   setPageNumber(pageNumber, pageLabel) {
11477     this.pageNumber = pageNumber;
11478     this.pageLabel = pageLabel;
11479     this.#updateUIState(false);
11480   }
11481   setPagesCount(pagesCount, hasPageLabels) {
11482     this.pagesCount = pagesCount;
11483     this.hasPageLabels = hasPageLabels;
11484     this.#updateUIState(true);
11485   }
11486   setPageScale(pageScaleValue, pageScale) {
11487     this.pageScaleValue = (pageScaleValue || pageScale).toString();
11488     this.pageScale = pageScale;
11489     this.#updateUIState(false);
11490   }
11491   reset() {
11492     this.#colorPicker = null;
11493     this.pageNumber = 0;
11494     this.pageLabel = null;
11495     this.hasPageLabels = false;
11496     this.pagesCount = 0;
11497     this.pageScaleValue = DEFAULT_SCALE_VALUE;
11498     this.pageScale = DEFAULT_SCALE;
11499     this.#updateUIState(true);
11500     this.updateLoadingIndicatorState();
11501     this.#editorModeChanged({
11502       mode: AnnotationEditorType.DISABLE
11503     });
11504   }
11505   #bindListeners(buttons) {
11506     const {
11507       eventBus
11508     } = this;
11509     const {
11510       editorHighlightColorPicker,
11511       editorHighlightButton,
11512       pageNumber,
11513       scaleSelect
11514     } = this.#opts;
11515     const self = this;
11516     for (const {
11517       element,
11518       eventName,
11519       eventDetails,
11520       telemetry
11521     } of buttons) {
11522       element.addEventListener("click", evt => {
11523         if (eventName !== null) {
11524           eventBus.dispatch(eventName, {
11525             source: this,
11526             ...eventDetails,
11527             isFromKeyboard: evt.detail === 0
11528           });
11529         }
11530         if (telemetry) {
11531           eventBus.dispatch("reporttelemetry", {
11532             source: this,
11533             details: telemetry
11534           });
11535         }
11536       });
11537     }
11538     pageNumber.addEventListener("click", function () {
11539       this.select();
11540     });
11541     pageNumber.addEventListener("change", function () {
11542       eventBus.dispatch("pagenumberchanged", {
11543         source: self,
11544         value: this.value
11545       });
11546     });
11547     scaleSelect.addEventListener("change", function () {
11548       if (this.value === "custom") {
11549         return;
11550       }
11551       eventBus.dispatch("scalechanged", {
11552         source: self,
11553         value: this.value
11554       });
11555     });
11556     scaleSelect.addEventListener("click", function ({
11557       target
11558     }) {
11559       if (this.value === self.pageScaleValue && target.tagName.toUpperCase() === "OPTION") {
11560         this.blur();
11561       }
11562     });
11563     scaleSelect.oncontextmenu = noContextMenu;
11564     eventBus._on("annotationeditormodechanged", this.#editorModeChanged.bind(this));
11565     eventBus._on("showannotationeditorui", ({
11566       mode
11567     }) => {
11568       switch (mode) {
11569         case AnnotationEditorType.HIGHLIGHT:
11570           editorHighlightButton.click();
11571           break;
11572       }
11573     });
11574     eventBus._on("toolbardensity", this.#updateToolbarDensity.bind(this));
11575     if (editorHighlightColorPicker) {
11576       eventBus._on("annotationeditoruimanager", ({
11577         uiManager
11578       }) => {
11579         const cp = this.#colorPicker = new ColorPicker({
11580           uiManager
11581         });
11582         uiManager.setMainHighlightColorPicker(cp);
11583         editorHighlightColorPicker.append(cp.renderMainDropdown());
11584       });
11585       eventBus._on("mainhighlightcolorpickerupdatecolor", ({
11586         value
11587       }) => {
11588         this.#colorPicker?.updateColor(value);
11589       });
11590     }
11591   }
11592   #editorModeChanged({
11593     mode
11594   }) {
11595     const {
11596       editorFreeTextButton,
11597       editorFreeTextParamsToolbar,
11598       editorHighlightButton,
11599       editorHighlightParamsToolbar,
11600       editorInkButton,
11601       editorInkParamsToolbar,
11602       editorStampButton,
11603       editorStampParamsToolbar,
11604       editorSignatureButton,
11605       editorSignatureParamsToolbar
11606     } = this.#opts;
11607     toggleExpandedBtn(editorFreeTextButton, mode === AnnotationEditorType.FREETEXT, editorFreeTextParamsToolbar);
11608     toggleExpandedBtn(editorHighlightButton, mode === AnnotationEditorType.HIGHLIGHT, editorHighlightParamsToolbar);
11609     toggleExpandedBtn(editorInkButton, mode === AnnotationEditorType.INK, editorInkParamsToolbar);
11610     toggleExpandedBtn(editorStampButton, mode === AnnotationEditorType.STAMP, editorStampParamsToolbar);
11611     toggleExpandedBtn(editorSignatureButton, mode === AnnotationEditorType.SIGNATURE, editorSignatureParamsToolbar);
11612     const isDisable = mode === AnnotationEditorType.DISABLE;
11613     editorFreeTextButton.disabled = isDisable;
11614     editorHighlightButton.disabled = isDisable;
11615     editorInkButton.disabled = isDisable;
11616     editorStampButton.disabled = isDisable;
11617     editorSignatureButton.disabled = isDisable;
11618   }
11619   #updateUIState(resetNumPages = false) {
11620     const {
11621       pageNumber,
11622       pagesCount,
11623       pageScaleValue,
11624       pageScale
11625     } = this;
11626     const opts = this.#opts;
11627     if (resetNumPages) {
11628       if (this.hasPageLabels) {
11629         opts.pageNumber.type = "text";
11630         opts.numPages.setAttribute("data-l10n-id", "pdfjs-page-of-pages");
11631       } else {
11632         opts.pageNumber.type = "number";
11633         opts.numPages.setAttribute("data-l10n-id", "pdfjs-of-pages");
11634         opts.numPages.setAttribute("data-l10n-args", JSON.stringify({
11635           pagesCount
11636         }));
11637       }
11638       opts.pageNumber.max = pagesCount;
11639     }
11640     if (this.hasPageLabels) {
11641       opts.pageNumber.value = this.pageLabel;
11642       opts.numPages.setAttribute("data-l10n-args", JSON.stringify({
11643         pageNumber,
11644         pagesCount
11645       }));
11646     } else {
11647       opts.pageNumber.value = pageNumber;
11648     }
11649     opts.previous.disabled = pageNumber <= 1;
11650     opts.next.disabled = pageNumber >= pagesCount;
11651     opts.zoomOut.disabled = pageScale <= MIN_SCALE;
11652     opts.zoomIn.disabled = pageScale >= MAX_SCALE;
11653     let predefinedValueFound = false;
11654     for (const option of opts.scaleSelect.options) {
11655       if (option.value !== pageScaleValue) {
11656         option.selected = false;
11657         continue;
11658       }
11659       option.selected = true;
11660       predefinedValueFound = true;
11661     }
11662     if (!predefinedValueFound) {
11663       opts.customScaleOption.selected = true;
11664       opts.customScaleOption.setAttribute("data-l10n-args", JSON.stringify({
11665         scale: Math.round(pageScale * 10000) / 100
11666       }));
11667     }
11668   }
11669   updateLoadingIndicatorState(loading = false) {
11670     const {
11671       pageNumber
11672     } = this.#opts;
11673     pageNumber.classList.toggle("loading", loading);
11674   }
11677 ;// ./web/view_history.js
11678 const DEFAULT_VIEW_HISTORY_CACHE_SIZE = 20;
11679 class ViewHistory {
11680   constructor(fingerprint, cacheSize = DEFAULT_VIEW_HISTORY_CACHE_SIZE) {
11681     this.fingerprint = fingerprint;
11682     this.cacheSize = cacheSize;
11683     this._initializedPromise = this._readFromStorage().then(databaseStr => {
11684       const database = JSON.parse(databaseStr || "{}");
11685       let index = -1;
11686       if (!Array.isArray(database.files)) {
11687         database.files = [];
11688       } else {
11689         while (database.files.length >= this.cacheSize) {
11690           database.files.shift();
11691         }
11692         for (let i = 0, ii = database.files.length; i < ii; i++) {
11693           const branch = database.files[i];
11694           if (branch.fingerprint === this.fingerprint) {
11695             index = i;
11696             break;
11697           }
11698         }
11699       }
11700       if (index === -1) {
11701         index = database.files.push({
11702           fingerprint: this.fingerprint
11703         }) - 1;
11704       }
11705       this.file = database.files[index];
11706       this.database = database;
11707     });
11708   }
11709   async _writeToStorage() {
11710     const databaseStr = JSON.stringify(this.database);
11711     sessionStorage.setItem("pdfjs.history", databaseStr);
11712   }
11713   async _readFromStorage() {
11714     return sessionStorage.getItem("pdfjs.history");
11715   }
11716   async set(name, val) {
11717     await this._initializedPromise;
11718     this.file[name] = val;
11719     return this._writeToStorage();
11720   }
11721   async setMultiple(properties) {
11722     await this._initializedPromise;
11723     for (const name in properties) {
11724       this.file[name] = properties[name];
11725     }
11726     return this._writeToStorage();
11727   }
11728   async get(name, defaultValue) {
11729     await this._initializedPromise;
11730     const val = this.file[name];
11731     return val !== undefined ? val : defaultValue;
11732   }
11733   async getMultiple(properties) {
11734     await this._initializedPromise;
11735     const values = Object.create(null);
11736     for (const name in properties) {
11737       const val = this.file[name];
11738       values[name] = val !== undefined ? val : properties[name];
11739     }
11740     return values;
11741   }
11744 ;// ./web/app.js
11778 const FORCE_PAGES_LOADED_TIMEOUT = 10000;
11779 const ViewOnLoad = {
11780   UNKNOWN: -1,
11781   PREVIOUS: 0,
11782   INITIAL: 1
11784 const PDFViewerApplication = {
11785   initialBookmark: document.location.hash.substring(1),
11786   _initializedCapability: {
11787     ...Promise.withResolvers(),
11788     settled: false
11789   },
11790   appConfig: null,
11791   pdfDocument: null,
11792   pdfLoadingTask: null,
11793   printService: null,
11794   pdfViewer: null,
11795   pdfThumbnailViewer: null,
11796   pdfRenderingQueue: null,
11797   pdfPresentationMode: null,
11798   pdfDocumentProperties: null,
11799   pdfLinkService: null,
11800   pdfHistory: null,
11801   pdfSidebar: null,
11802   pdfOutlineViewer: null,
11803   pdfAttachmentViewer: null,
11804   pdfLayerViewer: null,
11805   pdfCursorTools: null,
11806   pdfScriptingManager: null,
11807   store: null,
11808   downloadManager: null,
11809   overlayManager: null,
11810   preferences: new Preferences(),
11811   toolbar: null,
11812   secondaryToolbar: null,
11813   eventBus: null,
11814   l10n: null,
11815   annotationEditorParams: null,
11816   imageAltTextSettings: null,
11817   isInitialViewSet: false,
11818   isViewerEmbedded: window.parent !== window,
11819   url: "",
11820   baseUrl: "",
11821   mlManager: null,
11822   _downloadUrl: "",
11823   _eventBusAbortController: null,
11824   _windowAbortController: null,
11825   _globalAbortController: new AbortController(),
11826   documentInfo: null,
11827   metadata: null,
11828   _contentDispositionFilename: null,
11829   _contentLength: null,
11830   _saveInProgress: false,
11831   _wheelUnusedTicks: 0,
11832   _wheelUnusedFactor: 1,
11833   _touchManager: null,
11834   _touchUnusedTicks: 0,
11835   _touchUnusedFactor: 1,
11836   _PDFBug: null,
11837   _hasAnnotationEditors: false,
11838   _title: document.title,
11839   _printAnnotationStoragePromise: null,
11840   _isCtrlKeyDown: false,
11841   _caretBrowsing: null,
11842   _isScrolling: false,
11843   editorUndoBar: null,
11844   async initialize(appConfig) {
11845     this.appConfig = appConfig;
11846     try {
11847       await this.preferences.initializedPromise;
11848     } catch (ex) {
11849       console.error("initialize:", ex);
11850     }
11851     if (AppOptions.get("pdfBugEnabled")) {
11852       await this._parseHashParams();
11853     }
11854     if (AppOptions.get("enableAltText")) {
11855       this.mlManager = new MLManager({
11856         enableGuessAltText: AppOptions.get("enableGuessAltText"),
11857         enableAltTextModelDownload: AppOptions.get("enableAltTextModelDownload"),
11858         altTextLearnMoreUrl: AppOptions.get("altTextLearnMoreUrl")
11859       });
11860     }
11861     this.l10n = await this.externalServices.createL10n();
11862     document.getElementsByTagName("html")[0].dir = this.l10n.getDirection();
11863     if (this.isViewerEmbedded && AppOptions.get("externalLinkTarget") === LinkTarget.NONE) {
11864       AppOptions.set("externalLinkTarget", LinkTarget.TOP);
11865     }
11866     await this._initializeViewerComponents();
11867     this.bindEvents();
11868     this.bindWindowEvents();
11869     this._initializedCapability.settled = true;
11870     this._initializedCapability.resolve();
11871   },
11872   async _parseHashParams() {
11873     const hash = document.location.hash.substring(1);
11874     if (!hash) {
11875       return;
11876     }
11877     const {
11878         mainContainer,
11879         viewerContainer
11880       } = this.appConfig,
11881       params = parseQueryString(hash);
11882     const loadPDFBug = async () => {
11883       if (this._PDFBug) {
11884         return;
11885       }
11886       const {
11887         PDFBug
11888       } = await import(/*webpackIgnore: true*/AppOptions.get("debuggerSrc"));
11889       this._PDFBug = PDFBug;
11890     };
11891     if (params.get("disableworker") === "true") {
11892       try {
11893         GlobalWorkerOptions.workerSrc ||= AppOptions.get("workerSrc");
11894         await import(/*webpackIgnore: true*/PDFWorker.workerSrc);
11895       } catch (ex) {
11896         console.error("_parseHashParams:", ex);
11897       }
11898     }
11899     if (params.has("textlayer")) {
11900       switch (params.get("textlayer")) {
11901         case "off":
11902           AppOptions.set("textLayerMode", TextLayerMode.DISABLE);
11903           break;
11904         case "visible":
11905         case "shadow":
11906         case "hover":
11907           viewerContainer.classList.add(`textLayer-${params.get("textlayer")}`);
11908           try {
11909             await loadPDFBug();
11910             this._PDFBug.loadCSS();
11911           } catch (ex) {
11912             console.error("_parseHashParams:", ex);
11913           }
11914           break;
11915       }
11916     }
11917     if (params.has("pdfbug")) {
11918       AppOptions.setAll({
11919         pdfBug: true,
11920         fontExtraProperties: true
11921       });
11922       const enabled = params.get("pdfbug").split(",");
11923       try {
11924         await loadPDFBug();
11925         this._PDFBug.init(mainContainer, enabled);
11926       } catch (ex) {
11927         console.error("_parseHashParams:", ex);
11928       }
11929     }
11930     const opts = {
11931       disableAutoFetch: x => x === "true",
11932       disableFontFace: x => x === "true",
11933       disableHistory: x => x === "true",
11934       disableRange: x => x === "true",
11935       disableStream: x => x === "true",
11936       verbosity: x => x | 0
11937     };
11938     for (const name in opts) {
11939       const check = opts[name],
11940         key = name.toLowerCase();
11941       if (params.has(key)) {
11942         AppOptions.set(name, check(params.get(key)));
11943       }
11944     }
11945   },
11946   async _initializeViewerComponents() {
11947     const {
11948       appConfig,
11949       externalServices,
11950       l10n
11951     } = this;
11952     const eventBus = new FirefoxEventBus(AppOptions.get("allowedGlobalEvents"), externalServices, AppOptions.get("isInAutomation"));
11953     this.eventBus = AppOptions.eventBus = eventBus;
11954     this.mlManager?.setEventBus(eventBus, this._globalAbortController.signal);
11955     this.overlayManager = new OverlayManager();
11956     const pdfRenderingQueue = new PDFRenderingQueue();
11957     pdfRenderingQueue.onIdle = this._cleanup.bind(this);
11958     this.pdfRenderingQueue = pdfRenderingQueue;
11959     const pdfLinkService = new PDFLinkService({
11960       eventBus,
11961       externalLinkTarget: AppOptions.get("externalLinkTarget"),
11962       externalLinkRel: AppOptions.get("externalLinkRel"),
11963       ignoreDestinationZoom: AppOptions.get("ignoreDestinationZoom")
11964     });
11965     this.pdfLinkService = pdfLinkService;
11966     const downloadManager = this.downloadManager = new DownloadManager();
11967     const findController = new PDFFindController({
11968       linkService: pdfLinkService,
11969       eventBus,
11970       updateMatchesCountOnProgress: true
11971     });
11972     this.findController = findController;
11973     const pdfScriptingManager = new PDFScriptingManager({
11974       eventBus,
11975       externalServices,
11976       docProperties: this._scriptingDocProperties.bind(this)
11977     });
11978     this.pdfScriptingManager = pdfScriptingManager;
11979     const container = appConfig.mainContainer,
11980       viewer = appConfig.viewerContainer;
11981     const annotationEditorMode = AppOptions.get("annotationEditorMode");
11982     const pageColors = AppOptions.get("forcePageColors") || window.matchMedia("(forced-colors: active)").matches ? {
11983       background: AppOptions.get("pageColorsBackground"),
11984       foreground: AppOptions.get("pageColorsForeground")
11985     } : null;
11986     let altTextManager;
11987     if (AppOptions.get("enableUpdatedAddImage")) {
11988       altTextManager = appConfig.newAltTextDialog ? new NewAltTextManager(appConfig.newAltTextDialog, this.overlayManager, eventBus) : null;
11989     } else {
11990       altTextManager = appConfig.altTextDialog ? new AltTextManager(appConfig.altTextDialog, container, this.overlayManager, eventBus) : null;
11991     }
11992     if (appConfig.editorUndoBar) {
11993       this.editorUndoBar = new EditorUndoBar(appConfig.editorUndoBar, eventBus);
11994     }
11995     const enableHWA = AppOptions.get("enableHWA");
11996     const pdfViewer = new PDFViewer({
11997       container,
11998       viewer,
11999       eventBus,
12000       renderingQueue: pdfRenderingQueue,
12001       linkService: pdfLinkService,
12002       downloadManager,
12003       altTextManager,
12004       editorUndoBar: this.editorUndoBar,
12005       findController,
12006       scriptingManager: AppOptions.get("enableScripting") && pdfScriptingManager,
12007       l10n,
12008       textLayerMode: AppOptions.get("textLayerMode"),
12009       annotationMode: AppOptions.get("annotationMode"),
12010       annotationEditorMode,
12011       annotationEditorHighlightColors: AppOptions.get("highlightEditorColors"),
12012       enableHighlightFloatingButton: AppOptions.get("enableHighlightFloatingButton"),
12013       enableUpdatedAddImage: AppOptions.get("enableUpdatedAddImage"),
12014       enableNewAltTextWhenAddingImage: AppOptions.get("enableNewAltTextWhenAddingImage"),
12015       imageResourcesPath: AppOptions.get("imageResourcesPath"),
12016       enablePrintAutoRotate: AppOptions.get("enablePrintAutoRotate"),
12017       maxCanvasPixels: AppOptions.get("maxCanvasPixels"),
12018       enablePermissions: AppOptions.get("enablePermissions"),
12019       pageColors,
12020       mlManager: this.mlManager,
12021       abortSignal: this._globalAbortController.signal,
12022       enableHWA,
12023       supportsPinchToZoom: this.supportsPinchToZoom
12024     });
12025     this.pdfViewer = pdfViewer;
12026     pdfRenderingQueue.setViewer(pdfViewer);
12027     pdfLinkService.setViewer(pdfViewer);
12028     pdfScriptingManager.setViewer(pdfViewer);
12029     if (appConfig.sidebar?.thumbnailView) {
12030       this.pdfThumbnailViewer = new PDFThumbnailViewer({
12031         container: appConfig.sidebar.thumbnailView,
12032         eventBus,
12033         renderingQueue: pdfRenderingQueue,
12034         linkService: pdfLinkService,
12035         pageColors,
12036         abortSignal: this._globalAbortController.signal,
12037         enableHWA
12038       });
12039       pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
12040     }
12041     if (!this.isViewerEmbedded && !AppOptions.get("disableHistory")) {
12042       this.pdfHistory = new PDFHistory({
12043         linkService: pdfLinkService,
12044         eventBus
12045       });
12046       pdfLinkService.setHistory(this.pdfHistory);
12047     }
12048     if (!this.supportsIntegratedFind && appConfig.findBar) {
12049       this.findBar = new PDFFindBar(appConfig.findBar, appConfig.principalContainer, eventBus);
12050     }
12051     if (appConfig.annotationEditorParams) {
12052       if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
12053         const editorSignatureButton = appConfig.toolbar?.editorSignatureButton;
12054         if (editorSignatureButton && AppOptions.get("enableSignatureEditor")) {
12055           editorSignatureButton.parentElement.hidden = false;
12056         }
12057         this.annotationEditorParams = new AnnotationEditorParams(appConfig.annotationEditorParams, eventBus);
12058       } else {
12059         for (const id of ["editorModeButtons", "editorModeSeparator"]) {
12060           document.getElementById(id)?.classList.add("hidden");
12061         }
12062       }
12063     }
12064     if (this.mlManager && appConfig.secondaryToolbar?.imageAltTextSettingsButton) {
12065       this.imageAltTextSettings = new ImageAltTextSettings(appConfig.altTextSettingsDialog, this.overlayManager, eventBus, this.mlManager);
12066     }
12067     if (appConfig.documentProperties) {
12068       this.pdfDocumentProperties = new PDFDocumentProperties(appConfig.documentProperties, this.overlayManager, eventBus, l10n, () => this._docFilename);
12069     }
12070     if (appConfig.secondaryToolbar?.cursorHandToolButton) {
12071       this.pdfCursorTools = new PDFCursorTools({
12072         container,
12073         eventBus,
12074         cursorToolOnLoad: AppOptions.get("cursorToolOnLoad")
12075       });
12076     }
12077     if (appConfig.toolbar) {
12078       this.toolbar = new Toolbar(appConfig.toolbar, eventBus, AppOptions.get("toolbarDensity"));
12079     }
12080     if (appConfig.secondaryToolbar) {
12081       if (AppOptions.get("enableAltText")) {
12082         appConfig.secondaryToolbar.imageAltTextSettingsButton?.classList.remove("hidden");
12083         appConfig.secondaryToolbar.imageAltTextSettingsSeparator?.classList.remove("hidden");
12084       }
12085       this.secondaryToolbar = new SecondaryToolbar(appConfig.secondaryToolbar, eventBus);
12086     }
12087     if (this.supportsFullscreen && appConfig.secondaryToolbar?.presentationModeButton) {
12088       this.pdfPresentationMode = new PDFPresentationMode({
12089         container,
12090         pdfViewer,
12091         eventBus
12092       });
12093     }
12094     if (appConfig.passwordOverlay) {
12095       this.passwordPrompt = new PasswordPrompt(appConfig.passwordOverlay, this.overlayManager, this.isViewerEmbedded);
12096     }
12097     if (appConfig.sidebar?.outlineView) {
12098       this.pdfOutlineViewer = new PDFOutlineViewer({
12099         container: appConfig.sidebar.outlineView,
12100         eventBus,
12101         l10n,
12102         linkService: pdfLinkService,
12103         downloadManager
12104       });
12105     }
12106     if (appConfig.sidebar?.attachmentsView) {
12107       this.pdfAttachmentViewer = new PDFAttachmentViewer({
12108         container: appConfig.sidebar.attachmentsView,
12109         eventBus,
12110         l10n,
12111         downloadManager
12112       });
12113     }
12114     if (appConfig.sidebar?.layersView) {
12115       this.pdfLayerViewer = new PDFLayerViewer({
12116         container: appConfig.sidebar.layersView,
12117         eventBus,
12118         l10n
12119       });
12120     }
12121     if (appConfig.sidebar) {
12122       this.pdfSidebar = new PDFSidebar({
12123         elements: appConfig.sidebar,
12124         eventBus,
12125         l10n
12126       });
12127       this.pdfSidebar.onToggled = this.forceRendering.bind(this);
12128       this.pdfSidebar.onUpdateThumbnails = () => {
12129         for (const pageView of pdfViewer.getCachedPageViews()) {
12130           if (pageView.renderingState === RenderingStates.FINISHED) {
12131             this.pdfThumbnailViewer.getThumbnail(pageView.id - 1)?.setImage(pageView);
12132           }
12133         }
12134         this.pdfThumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber);
12135       };
12136     }
12137   },
12138   async run(config) {
12139     await this.initialize(config);
12140     const {
12141       appConfig,
12142       eventBus
12143     } = this;
12144     let file;
12145     file = window.location.href;
12146     if (!AppOptions.get("supportsDocumentFonts")) {
12147       AppOptions.set("disableFontFace", true);
12148       this.l10n.get("pdfjs-web-fonts-disabled").then(msg => {
12149         console.warn(msg);
12150       });
12151     }
12152     if (!this.supportsPrinting) {
12153       appConfig.toolbar?.print?.classList.add("hidden");
12154       appConfig.secondaryToolbar?.printButton.classList.add("hidden");
12155     }
12156     if (!this.supportsFullscreen) {
12157       appConfig.secondaryToolbar?.presentationModeButton.classList.add("hidden");
12158     }
12159     if (this.supportsIntegratedFind) {
12160       appConfig.findBar?.toggleButton?.classList.add("hidden");
12161     }
12162     this.setTitleUsingUrl(file, file);
12163     this.externalServices.initPassiveLoading();
12164   },
12165   get externalServices() {
12166     return shadow(this, "externalServices", new ExternalServices());
12167   },
12168   get initialized() {
12169     return this._initializedCapability.settled;
12170   },
12171   get initializedPromise() {
12172     return this._initializedCapability.promise;
12173   },
12174   updateZoom(steps, scaleFactor, origin) {
12175     if (this.pdfViewer.isInPresentationMode) {
12176       return;
12177     }
12178     this.pdfViewer.updateScale({
12179       drawingDelay: AppOptions.get("defaultZoomDelay"),
12180       steps,
12181       scaleFactor,
12182       origin
12183     });
12184   },
12185   zoomIn() {
12186     this.updateZoom(1);
12187   },
12188   zoomOut() {
12189     this.updateZoom(-1);
12190   },
12191   zoomReset() {
12192     if (this.pdfViewer.isInPresentationMode) {
12193       return;
12194     }
12195     this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
12196   },
12197   touchPinchCallback(origin, prevDistance, distance) {
12198     if (this.supportsPinchToZoom) {
12199       const newScaleFactor = this._accumulateFactor(this.pdfViewer.currentScale, distance / prevDistance, "_touchUnusedFactor");
12200       this.updateZoom(null, newScaleFactor, origin);
12201     } else {
12202       const PIXELS_PER_LINE_SCALE = 30;
12203       const ticks = this._accumulateTicks((distance - prevDistance) / PIXELS_PER_LINE_SCALE, "_touchUnusedTicks");
12204       this.updateZoom(ticks, null, origin);
12205     }
12206   },
12207   touchPinchEndCallback() {
12208     this._touchUnusedTicks = 0;
12209     this._touchUnusedFactor = 1;
12210   },
12211   get pagesCount() {
12212     return this.pdfDocument ? this.pdfDocument.numPages : 0;
12213   },
12214   get page() {
12215     return this.pdfViewer.currentPageNumber;
12216   },
12217   set page(val) {
12218     this.pdfViewer.currentPageNumber = val;
12219   },
12220   get supportsPrinting() {
12221     return PDFPrintServiceFactory.supportsPrinting;
12222   },
12223   get supportsFullscreen() {
12224     return shadow(this, "supportsFullscreen", document.fullscreenEnabled);
12225   },
12226   get supportsPinchToZoom() {
12227     return shadow(this, "supportsPinchToZoom", AppOptions.get("supportsPinchToZoom"));
12228   },
12229   get supportsIntegratedFind() {
12230     return shadow(this, "supportsIntegratedFind", AppOptions.get("supportsIntegratedFind"));
12231   },
12232   get loadingBar() {
12233     const barElement = document.getElementById("loadingBar");
12234     const bar = barElement ? new ProgressBar(barElement) : null;
12235     return shadow(this, "loadingBar", bar);
12236   },
12237   get supportsMouseWheelZoomCtrlKey() {
12238     return shadow(this, "supportsMouseWheelZoomCtrlKey", AppOptions.get("supportsMouseWheelZoomCtrlKey"));
12239   },
12240   get supportsMouseWheelZoomMetaKey() {
12241     return shadow(this, "supportsMouseWheelZoomMetaKey", AppOptions.get("supportsMouseWheelZoomMetaKey"));
12242   },
12243   get supportsCaretBrowsingMode() {
12244     return AppOptions.get("supportsCaretBrowsingMode");
12245   },
12246   moveCaret(isUp, select) {
12247     this._caretBrowsing ||= new CaretBrowsingMode(this._globalAbortController.signal, this.appConfig.mainContainer, this.appConfig.viewerContainer, this.appConfig.toolbar?.container);
12248     this._caretBrowsing.moveCaret(isUp, select);
12249   },
12250   setTitleUsingUrl(url = "", downloadUrl = null) {
12251     this.url = url;
12252     this.baseUrl = url.split("#", 1)[0];
12253     if (downloadUrl) {
12254       this._downloadUrl = downloadUrl === url ? this.baseUrl : downloadUrl.split("#", 1)[0];
12255     }
12256     if (isDataScheme(url)) {
12257       this._hideViewBookmark();
12258     } else {
12259       AppOptions.set("docBaseUrl", this.baseUrl);
12260     }
12261     let title = getPdfFilenameFromUrl(url, "");
12262     if (!title) {
12263       try {
12264         title = decodeURIComponent(getFilenameFromUrl(url));
12265       } catch {}
12266     }
12267     this.setTitle(title || url);
12268   },
12269   setTitle(title = this._title) {
12270     this._title = title;
12271     if (this.isViewerEmbedded) {
12272       return;
12273     }
12274     const editorIndicator = this._hasAnnotationEditors && !this.pdfRenderingQueue.printing;
12275     document.title = `${editorIndicator ? "* " : ""}${title}`;
12276   },
12277   get _docFilename() {
12278     return this._contentDispositionFilename || getPdfFilenameFromUrl(this.url);
12279   },
12280   _hideViewBookmark() {
12281     const {
12282       secondaryToolbar
12283     } = this.appConfig;
12284     secondaryToolbar?.viewBookmarkButton.classList.add("hidden");
12285     if (secondaryToolbar?.presentationModeButton.classList.contains("hidden")) {
12286       document.getElementById("viewBookmarkSeparator")?.classList.add("hidden");
12287     }
12288   },
12289   async close() {
12290     this._unblockDocumentLoadEvent();
12291     this._hideViewBookmark();
12292     if (!this.pdfLoadingTask) {
12293       return;
12294     }
12295     const promises = [];
12296     promises.push(this.pdfLoadingTask.destroy());
12297     this.pdfLoadingTask = null;
12298     if (this.pdfDocument) {
12299       this.pdfDocument = null;
12300       this.pdfThumbnailViewer?.setDocument(null);
12301       this.pdfViewer.setDocument(null);
12302       this.pdfLinkService.setDocument(null);
12303       this.pdfDocumentProperties?.setDocument(null);
12304     }
12305     this.pdfLinkService.externalLinkEnabled = true;
12306     this.store = null;
12307     this.isInitialViewSet = false;
12308     this.url = "";
12309     this.baseUrl = "";
12310     this._downloadUrl = "";
12311     this.documentInfo = null;
12312     this.metadata = null;
12313     this._contentDispositionFilename = null;
12314     this._contentLength = null;
12315     this._saveInProgress = false;
12316     this._hasAnnotationEditors = false;
12317     promises.push(this.pdfScriptingManager.destroyPromise, this.passwordPrompt.close());
12318     this.setTitle();
12319     this.pdfSidebar?.reset();
12320     this.pdfOutlineViewer?.reset();
12321     this.pdfAttachmentViewer?.reset();
12322     this.pdfLayerViewer?.reset();
12323     this.pdfHistory?.reset();
12324     this.findBar?.reset();
12325     this.toolbar?.reset();
12326     this.secondaryToolbar?.reset();
12327     this._PDFBug?.cleanup();
12328     await Promise.all(promises);
12329   },
12330   async open(args) {
12331     if (this.pdfLoadingTask) {
12332       await this.close();
12333     }
12334     const workerParams = AppOptions.getAll(OptionKind.WORKER);
12335     Object.assign(GlobalWorkerOptions, workerParams);
12336     if (args.data && isPdfFile(args.filename)) {
12337       this._contentDispositionFilename = args.filename;
12338     }
12339     const apiParams = AppOptions.getAll(OptionKind.API);
12340     const loadingTask = getDocument({
12341       ...apiParams,
12342       ...args
12343     });
12344     this.pdfLoadingTask = loadingTask;
12345     loadingTask.onPassword = (updateCallback, reason) => {
12346       if (this.isViewerEmbedded) {
12347         this._unblockDocumentLoadEvent();
12348       }
12349       this.pdfLinkService.externalLinkEnabled = false;
12350       this.passwordPrompt.setUpdateCallback(updateCallback, reason);
12351       this.passwordPrompt.open();
12352     };
12353     loadingTask.onProgress = ({
12354       loaded,
12355       total
12356     }) => {
12357       this.progress(loaded / total);
12358     };
12359     return loadingTask.promise.then(pdfDocument => {
12360       this.load(pdfDocument);
12361     }, reason => {
12362       if (loadingTask !== this.pdfLoadingTask) {
12363         return undefined;
12364       }
12365       let key = "pdfjs-loading-error";
12366       if (reason instanceof InvalidPDFException) {
12367         key = "pdfjs-invalid-file-error";
12368       } else if (reason instanceof ResponseException) {
12369         key = reason.missing ? "pdfjs-missing-file-error" : "pdfjs-unexpected-response-error";
12370       }
12371       return this._documentError(key, {
12372         message: reason.message
12373       }).then(() => {
12374         throw reason;
12375       });
12376     });
12377   },
12378   async download() {
12379     let data;
12380     try {
12381       data = await this.pdfDocument.getData();
12382     } catch {}
12383     this.downloadManager.download(data, this._downloadUrl, this._docFilename);
12384   },
12385   async save() {
12386     if (this._saveInProgress) {
12387       return;
12388     }
12389     this._saveInProgress = true;
12390     await this.pdfScriptingManager.dispatchWillSave();
12391     try {
12392       const data = await this.pdfDocument.saveDocument();
12393       this.downloadManager.download(data, this._downloadUrl, this._docFilename);
12394     } catch (reason) {
12395       console.error(`Error when saving the document:`, reason);
12396       await this.download();
12397     } finally {
12398       await this.pdfScriptingManager.dispatchDidSave();
12399       this._saveInProgress = false;
12400     }
12401     if (this._hasAnnotationEditors) {
12402       this.externalServices.reportTelemetry({
12403         type: "editing",
12404         data: {
12405           type: "save",
12406           stats: this.pdfDocument?.annotationStorage.editorStats
12407         }
12408       });
12409     }
12410   },
12411   async downloadOrSave() {
12412     const {
12413       classList
12414     } = this.appConfig.appContainer;
12415     classList.add("wait");
12416     await (this.pdfDocument?.annotationStorage.size > 0 ? this.save() : this.download());
12417     classList.remove("wait");
12418   },
12419   async _documentError(key, moreInfo = null) {
12420     this._unblockDocumentLoadEvent();
12421     const message = await this._otherError(key || "pdfjs-loading-error", moreInfo);
12422     this.eventBus.dispatch("documenterror", {
12423       source: this,
12424       message,
12425       reason: moreInfo?.message ?? null
12426     });
12427   },
12428   async _otherError(key, moreInfo = null) {
12429     const message = await this.l10n.get(key);
12430     const moreInfoText = [`PDF.js v${version || "?"} (build: ${build || "?"})`];
12431     if (moreInfo) {
12432       moreInfoText.push(`Message: ${moreInfo.message}`);
12433       if (moreInfo.stack) {
12434         moreInfoText.push(`Stack: ${moreInfo.stack}`);
12435       } else {
12436         if (moreInfo.filename) {
12437           moreInfoText.push(`File: ${moreInfo.filename}`);
12438         }
12439         if (moreInfo.lineNumber) {
12440           moreInfoText.push(`Line: ${moreInfo.lineNumber}`);
12441         }
12442       }
12443     }
12444     console.error(`${message}\n\n${moreInfoText.join("\n")}`);
12445     return message;
12446   },
12447   progress(level) {
12448     const percent = Math.round(level * 100);
12449     if (!this.loadingBar || percent <= this.loadingBar.percent) {
12450       return;
12451     }
12452     this.loadingBar.percent = percent;
12453     if (this.pdfDocument?.loadingParams.disableAutoFetch ?? AppOptions.get("disableAutoFetch")) {
12454       this.loadingBar.setDisableAutoFetch();
12455     }
12456   },
12457   load(pdfDocument) {
12458     this.pdfDocument = pdfDocument;
12459     pdfDocument.getDownloadInfo().then(({
12460       length
12461     }) => {
12462       this._contentLength = length;
12463       this.loadingBar?.hide();
12464       firstPagePromise.then(() => {
12465         this.eventBus.dispatch("documentloaded", {
12466           source: this
12467         });
12468       });
12469     });
12470     const pageLayoutPromise = pdfDocument.getPageLayout().catch(() => {});
12471     const pageModePromise = pdfDocument.getPageMode().catch(() => {});
12472     const openActionPromise = pdfDocument.getOpenAction().catch(() => {});
12473     this.toolbar?.setPagesCount(pdfDocument.numPages, false);
12474     this.secondaryToolbar?.setPagesCount(pdfDocument.numPages);
12475     this.pdfLinkService.setDocument(pdfDocument);
12476     this.pdfDocumentProperties?.setDocument(pdfDocument);
12477     const pdfViewer = this.pdfViewer;
12478     pdfViewer.setDocument(pdfDocument);
12479     const {
12480       firstPagePromise,
12481       onePageRendered,
12482       pagesPromise
12483     } = pdfViewer;
12484     this.pdfThumbnailViewer?.setDocument(pdfDocument);
12485     const storedPromise = (this.store = new ViewHistory(pdfDocument.fingerprints[0])).getMultiple({
12486       page: null,
12487       zoom: DEFAULT_SCALE_VALUE,
12488       scrollLeft: "0",
12489       scrollTop: "0",
12490       rotation: null,
12491       sidebarView: SidebarView.UNKNOWN,
12492       scrollMode: ScrollMode.UNKNOWN,
12493       spreadMode: SpreadMode.UNKNOWN
12494     }).catch(() => {});
12495     firstPagePromise.then(pdfPage => {
12496       this.loadingBar?.setWidth(this.appConfig.viewerContainer);
12497       this._initializeAnnotationStorageCallbacks(pdfDocument);
12498       Promise.all([animationStarted, storedPromise, pageLayoutPromise, pageModePromise, openActionPromise]).then(async ([timeStamp, stored, pageLayout, pageMode, openAction]) => {
12499         const viewOnLoad = AppOptions.get("viewOnLoad");
12500         this._initializePdfHistory({
12501           fingerprint: pdfDocument.fingerprints[0],
12502           viewOnLoad,
12503           initialDest: openAction?.dest
12504         });
12505         const initialBookmark = this.initialBookmark;
12506         const zoom = AppOptions.get("defaultZoomValue");
12507         let hash = zoom ? `zoom=${zoom}` : null;
12508         let rotation = null;
12509         let sidebarView = AppOptions.get("sidebarViewOnLoad");
12510         let scrollMode = AppOptions.get("scrollModeOnLoad");
12511         let spreadMode = AppOptions.get("spreadModeOnLoad");
12512         if (stored?.page && viewOnLoad !== ViewOnLoad.INITIAL) {
12513           hash = `page=${stored.page}&zoom=${zoom || stored.zoom},` + `${stored.scrollLeft},${stored.scrollTop}`;
12514           rotation = parseInt(stored.rotation, 10);
12515           if (sidebarView === SidebarView.UNKNOWN) {
12516             sidebarView = stored.sidebarView | 0;
12517           }
12518           if (scrollMode === ScrollMode.UNKNOWN) {
12519             scrollMode = stored.scrollMode | 0;
12520           }
12521           if (spreadMode === SpreadMode.UNKNOWN) {
12522             spreadMode = stored.spreadMode | 0;
12523           }
12524         }
12525         if (pageMode && sidebarView === SidebarView.UNKNOWN) {
12526           sidebarView = apiPageModeToSidebarView(pageMode);
12527         }
12528         if (pageLayout && scrollMode === ScrollMode.UNKNOWN && spreadMode === SpreadMode.UNKNOWN) {
12529           const modes = apiPageLayoutToViewerModes(pageLayout);
12530           spreadMode = modes.spreadMode;
12531         }
12532         this.setInitialView(hash, {
12533           rotation,
12534           sidebarView,
12535           scrollMode,
12536           spreadMode
12537         });
12538         this.eventBus.dispatch("documentinit", {
12539           source: this
12540         });
12541         if (!this.isViewerEmbedded) {
12542           pdfViewer.focus();
12543         }
12544         await Promise.race([pagesPromise, new Promise(resolve => {
12545           setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT);
12546         })]);
12547         if (!initialBookmark && !hash) {
12548           return;
12549         }
12550         if (pdfViewer.hasEqualPageSizes) {
12551           return;
12552         }
12553         this.initialBookmark = initialBookmark;
12554         pdfViewer.currentScaleValue = pdfViewer.currentScaleValue;
12555         this.setInitialView(hash);
12556       }).catch(() => {
12557         this.setInitialView();
12558       }).then(function () {
12559         pdfViewer.update();
12560       });
12561     });
12562     pagesPromise.then(() => {
12563       this._unblockDocumentLoadEvent();
12564       this._initializeAutoPrint(pdfDocument, openActionPromise);
12565     }, reason => {
12566       this._documentError("pdfjs-loading-error", {
12567         message: reason.message
12568       });
12569     });
12570     onePageRendered.then(data => {
12571       this.externalServices.reportTelemetry({
12572         type: "pageInfo",
12573         timestamp: data.timestamp
12574       });
12575       if (this.pdfOutlineViewer) {
12576         pdfDocument.getOutline().then(outline => {
12577           if (pdfDocument !== this.pdfDocument) {
12578             return;
12579           }
12580           this.pdfOutlineViewer.render({
12581             outline,
12582             pdfDocument
12583           });
12584         });
12585       }
12586       if (this.pdfAttachmentViewer) {
12587         pdfDocument.getAttachments().then(attachments => {
12588           if (pdfDocument !== this.pdfDocument) {
12589             return;
12590           }
12591           this.pdfAttachmentViewer.render({
12592             attachments
12593           });
12594         });
12595       }
12596       if (this.pdfLayerViewer) {
12597         pdfViewer.optionalContentConfigPromise.then(optionalContentConfig => {
12598           if (pdfDocument !== this.pdfDocument) {
12599             return;
12600           }
12601           this.pdfLayerViewer.render({
12602             optionalContentConfig,
12603             pdfDocument
12604           });
12605         });
12606       }
12607     });
12608     this._initializePageLabels(pdfDocument);
12609     this._initializeMetadata(pdfDocument);
12610   },
12611   async _scriptingDocProperties(pdfDocument) {
12612     if (!this.documentInfo) {
12613       await new Promise(resolve => {
12614         this.eventBus._on("metadataloaded", resolve, {
12615           once: true
12616         });
12617       });
12618       if (pdfDocument !== this.pdfDocument) {
12619         return null;
12620       }
12621     }
12622     if (!this._contentLength) {
12623       await new Promise(resolve => {
12624         this.eventBus._on("documentloaded", resolve, {
12625           once: true
12626         });
12627       });
12628       if (pdfDocument !== this.pdfDocument) {
12629         return null;
12630       }
12631     }
12632     return {
12633       ...this.documentInfo,
12634       baseURL: this.baseUrl,
12635       filesize: this._contentLength,
12636       filename: this._docFilename,
12637       metadata: this.metadata?.getRaw(),
12638       authors: this.metadata?.get("dc:creator"),
12639       numPages: this.pagesCount,
12640       URL: this.url
12641     };
12642   },
12643   async _initializeAutoPrint(pdfDocument, openActionPromise) {
12644     const [openAction, jsActions] = await Promise.all([openActionPromise, this.pdfViewer.enableScripting ? null : pdfDocument.getJSActions()]);
12645     if (pdfDocument !== this.pdfDocument) {
12646       return;
12647     }
12648     let triggerAutoPrint = openAction?.action === "Print";
12649     if (jsActions) {
12650       console.warn("Warning: JavaScript support is not enabled");
12651       for (const name in jsActions) {
12652         if (triggerAutoPrint) {
12653           break;
12654         }
12655         switch (name) {
12656           case "WillClose":
12657           case "WillSave":
12658           case "DidSave":
12659           case "WillPrint":
12660           case "DidPrint":
12661             continue;
12662         }
12663         triggerAutoPrint = jsActions[name].some(js => AutoPrintRegExp.test(js));
12664       }
12665     }
12666     if (triggerAutoPrint) {
12667       this.triggerPrinting();
12668     }
12669   },
12670   async _initializeMetadata(pdfDocument) {
12671     const {
12672       info,
12673       metadata,
12674       contentDispositionFilename,
12675       contentLength
12676     } = await pdfDocument.getMetadata();
12677     if (pdfDocument !== this.pdfDocument) {
12678       return;
12679     }
12680     this.documentInfo = info;
12681     this.metadata = metadata;
12682     this._contentDispositionFilename ??= contentDispositionFilename;
12683     this._contentLength ??= contentLength;
12684     console.log(`PDF ${pdfDocument.fingerprints[0]} [${info.PDFFormatVersion} ` + `${(info.Producer || "-").trim()} / ${(info.Creator || "-").trim()}] ` + `(PDF.js: ${version || "?"} [${build || "?"}])`);
12685     let pdfTitle = info.Title;
12686     const metadataTitle = metadata?.get("dc:title");
12687     if (metadataTitle) {
12688       if (metadataTitle !== "Untitled" && !/[\uFFF0-\uFFFF]/g.test(metadataTitle)) {
12689         pdfTitle = metadataTitle;
12690       }
12691     }
12692     if (pdfTitle) {
12693       this.setTitle(`${pdfTitle} - ${this._contentDispositionFilename || this._title}`);
12694     } else if (this._contentDispositionFilename) {
12695       this.setTitle(this._contentDispositionFilename);
12696     }
12697     if (info.IsXFAPresent && !info.IsAcroFormPresent && !pdfDocument.isPureXfa) {
12698       if (pdfDocument.loadingParams.enableXfa) {
12699         console.warn("Warning: XFA Foreground documents are not supported");
12700       } else {
12701         console.warn("Warning: XFA support is not enabled");
12702       }
12703     } else if ((info.IsAcroFormPresent || info.IsXFAPresent) && !this.pdfViewer.renderForms) {
12704       console.warn("Warning: Interactive form support is not enabled");
12705     }
12706     if (info.IsSignaturesPresent) {
12707       console.warn("Warning: Digital signatures validation is not supported");
12708     }
12709     this.eventBus.dispatch("metadataloaded", {
12710       source: this
12711     });
12712   },
12713   async _initializePageLabels(pdfDocument) {
12714     const labels = await pdfDocument.getPageLabels();
12715     if (pdfDocument !== this.pdfDocument) {
12716       return;
12717     }
12718     if (!labels || AppOptions.get("disablePageLabels")) {
12719       return;
12720     }
12721     const numLabels = labels.length;
12722     let standardLabels = 0,
12723       emptyLabels = 0;
12724     for (let i = 0; i < numLabels; i++) {
12725       const label = labels[i];
12726       if (label === (i + 1).toString()) {
12727         standardLabels++;
12728       } else if (label === "") {
12729         emptyLabels++;
12730       } else {
12731         break;
12732       }
12733     }
12734     if (standardLabels >= numLabels || emptyLabels >= numLabels) {
12735       return;
12736     }
12737     const {
12738       pdfViewer,
12739       pdfThumbnailViewer,
12740       toolbar
12741     } = this;
12742     pdfViewer.setPageLabels(labels);
12743     pdfThumbnailViewer?.setPageLabels(labels);
12744     toolbar?.setPagesCount(numLabels, true);
12745     toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
12746   },
12747   _initializePdfHistory({
12748     fingerprint,
12749     viewOnLoad,
12750     initialDest = null
12751   }) {
12752     if (!this.pdfHistory) {
12753       return;
12754     }
12755     this.pdfHistory.initialize({
12756       fingerprint,
12757       resetHistory: viewOnLoad === ViewOnLoad.INITIAL,
12758       updateUrl: AppOptions.get("historyUpdateUrl")
12759     });
12760     if (this.pdfHistory.initialBookmark) {
12761       this.initialBookmark = this.pdfHistory.initialBookmark;
12762       this.initialRotation = this.pdfHistory.initialRotation;
12763     }
12764     if (initialDest && !this.initialBookmark && viewOnLoad === ViewOnLoad.UNKNOWN) {
12765       this.initialBookmark = JSON.stringify(initialDest);
12766       this.pdfHistory.push({
12767         explicitDest: initialDest,
12768         pageNumber: null
12769       });
12770     }
12771   },
12772   _initializeAnnotationStorageCallbacks(pdfDocument) {
12773     if (pdfDocument !== this.pdfDocument) {
12774       return;
12775     }
12776     const {
12777       annotationStorage
12778     } = pdfDocument;
12779     annotationStorage.onSetModified = () => {
12780       window.addEventListener("beforeunload", beforeUnload);
12781     };
12782     annotationStorage.onResetModified = () => {
12783       window.removeEventListener("beforeunload", beforeUnload);
12784     };
12785     annotationStorage.onAnnotationEditor = typeStr => {
12786       this._hasAnnotationEditors = !!typeStr;
12787       this.setTitle();
12788     };
12789   },
12790   setInitialView(storedHash, {
12791     rotation,
12792     sidebarView,
12793     scrollMode,
12794     spreadMode
12795   } = {}) {
12796     const setRotation = angle => {
12797       if (isValidRotation(angle)) {
12798         this.pdfViewer.pagesRotation = angle;
12799       }
12800     };
12801     const setViewerModes = (scroll, spread) => {
12802       if (isValidScrollMode(scroll)) {
12803         this.pdfViewer.scrollMode = scroll;
12804       }
12805       if (isValidSpreadMode(spread)) {
12806         this.pdfViewer.spreadMode = spread;
12807       }
12808     };
12809     this.isInitialViewSet = true;
12810     this.pdfSidebar?.setInitialView(sidebarView);
12811     setViewerModes(scrollMode, spreadMode);
12812     if (this.initialBookmark) {
12813       setRotation(this.initialRotation);
12814       delete this.initialRotation;
12815       this.pdfLinkService.setHash(this.initialBookmark);
12816       this.initialBookmark = null;
12817     } else if (storedHash) {
12818       setRotation(rotation);
12819       this.pdfLinkService.setHash(storedHash);
12820     }
12821     this.toolbar?.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel);
12822     this.secondaryToolbar?.setPageNumber(this.pdfViewer.currentPageNumber);
12823     if (!this.pdfViewer.currentScaleValue) {
12824       this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
12825     }
12826   },
12827   _cleanup() {
12828     if (!this.pdfDocument) {
12829       return;
12830     }
12831     this.pdfViewer.cleanup();
12832     this.pdfThumbnailViewer?.cleanup();
12833     this.pdfDocument.cleanup(AppOptions.get("fontExtraProperties"));
12834   },
12835   forceRendering() {
12836     this.pdfRenderingQueue.printing = !!this.printService;
12837     this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar?.visibleView === SidebarView.THUMBS;
12838     this.pdfRenderingQueue.renderHighestPriority();
12839   },
12840   beforePrint() {
12841     this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => this.pdfDocument?.annotationStorage.print);
12842     if (this.printService) {
12843       return;
12844     }
12845     if (!this.supportsPrinting) {
12846       this._otherError("pdfjs-printing-not-supported");
12847       return;
12848     }
12849     if (!this.pdfViewer.pageViewsReady) {
12850       this.l10n.get("pdfjs-printing-not-ready").then(msg => {
12851         window.alert(msg);
12852       });
12853       return;
12854     }
12855     this.printService = PDFPrintServiceFactory.createPrintService({
12856       pdfDocument: this.pdfDocument,
12857       pagesOverview: this.pdfViewer.getPagesOverview(),
12858       printContainer: this.appConfig.printContainer,
12859       printResolution: AppOptions.get("printResolution"),
12860       printAnnotationStoragePromise: this._printAnnotationStoragePromise
12861     });
12862     this.forceRendering();
12863     this.setTitle();
12864     this.printService.layout();
12865     if (this._hasAnnotationEditors) {
12866       this.externalServices.reportTelemetry({
12867         type: "editing",
12868         data: {
12869           type: "print",
12870           stats: this.pdfDocument?.annotationStorage.editorStats
12871         }
12872       });
12873     }
12874   },
12875   afterPrint() {
12876     if (this._printAnnotationStoragePromise) {
12877       this._printAnnotationStoragePromise.then(() => {
12878         this.pdfScriptingManager.dispatchDidPrint();
12879       });
12880       this._printAnnotationStoragePromise = null;
12881     }
12882     if (this.printService) {
12883       this.printService.destroy();
12884       this.printService = null;
12885       this.pdfDocument?.annotationStorage.resetModified();
12886     }
12887     this.forceRendering();
12888     this.setTitle();
12889   },
12890   rotatePages(delta) {
12891     this.pdfViewer.pagesRotation += delta;
12892   },
12893   requestPresentationMode() {
12894     this.pdfPresentationMode?.request();
12895   },
12896   triggerPrinting() {
12897     if (this.supportsPrinting) {
12898       window.print();
12899     }
12900   },
12901   bindEvents() {
12902     if (this._eventBusAbortController) {
12903       return;
12904     }
12905     const ac = this._eventBusAbortController = new AbortController();
12906     const opts = {
12907       signal: ac.signal
12908     };
12909     const {
12910       eventBus,
12911       externalServices,
12912       pdfDocumentProperties,
12913       pdfViewer,
12914       preferences
12915     } = this;
12916     eventBus._on("resize", onResize.bind(this), opts);
12917     eventBus._on("hashchange", onHashchange.bind(this), opts);
12918     eventBus._on("beforeprint", this.beforePrint.bind(this), opts);
12919     eventBus._on("afterprint", this.afterPrint.bind(this), opts);
12920     eventBus._on("pagerender", onPageRender.bind(this), opts);
12921     eventBus._on("pagerendered", onPageRendered.bind(this), opts);
12922     eventBus._on("updateviewarea", onUpdateViewarea.bind(this), opts);
12923     eventBus._on("pagechanging", onPageChanging.bind(this), opts);
12924     eventBus._on("scalechanging", onScaleChanging.bind(this), opts);
12925     eventBus._on("rotationchanging", onRotationChanging.bind(this), opts);
12926     eventBus._on("sidebarviewchanged", onSidebarViewChanged.bind(this), opts);
12927     eventBus._on("pagemode", onPageMode.bind(this), opts);
12928     eventBus._on("namedaction", onNamedAction.bind(this), opts);
12929     eventBus._on("presentationmodechanged", evt => pdfViewer.presentationModeState = evt.state, opts);
12930     eventBus._on("presentationmode", this.requestPresentationMode.bind(this), opts);
12931     eventBus._on("switchannotationeditormode", evt => pdfViewer.annotationEditorMode = evt, opts);
12932     eventBus._on("print", this.triggerPrinting.bind(this), opts);
12933     eventBus._on("download", this.downloadOrSave.bind(this), opts);
12934     eventBus._on("firstpage", () => this.page = 1, opts);
12935     eventBus._on("lastpage", () => this.page = this.pagesCount, opts);
12936     eventBus._on("nextpage", () => pdfViewer.nextPage(), opts);
12937     eventBus._on("previouspage", () => pdfViewer.previousPage(), opts);
12938     eventBus._on("zoomin", this.zoomIn.bind(this), opts);
12939     eventBus._on("zoomout", this.zoomOut.bind(this), opts);
12940     eventBus._on("zoomreset", this.zoomReset.bind(this), opts);
12941     eventBus._on("pagenumberchanged", onPageNumberChanged.bind(this), opts);
12942     eventBus._on("scalechanged", evt => pdfViewer.currentScaleValue = evt.value, opts);
12943     eventBus._on("rotatecw", this.rotatePages.bind(this, 90), opts);
12944     eventBus._on("rotateccw", this.rotatePages.bind(this, -90), opts);
12945     eventBus._on("optionalcontentconfig", evt => pdfViewer.optionalContentConfigPromise = evt.promise, opts);
12946     eventBus._on("switchscrollmode", evt => pdfViewer.scrollMode = evt.mode, opts);
12947     eventBus._on("scrollmodechanged", onViewerModesChanged.bind(this, "scrollMode"), opts);
12948     eventBus._on("switchspreadmode", evt => pdfViewer.spreadMode = evt.mode, opts);
12949     eventBus._on("spreadmodechanged", onViewerModesChanged.bind(this, "spreadMode"), opts);
12950     eventBus._on("imagealttextsettings", onImageAltTextSettings.bind(this), opts);
12951     eventBus._on("documentproperties", () => pdfDocumentProperties?.open(), opts);
12952     eventBus._on("findfromurlhash", onFindFromUrlHash.bind(this), opts);
12953     eventBus._on("updatefindmatchescount", onUpdateFindMatchesCount.bind(this), opts);
12954     eventBus._on("updatefindcontrolstate", onUpdateFindControlState.bind(this), opts);
12955     eventBus._on("annotationeditorstateschanged", evt => externalServices.updateEditorStates(evt), opts);
12956     eventBus._on("reporttelemetry", evt => externalServices.reportTelemetry(evt.details), opts);
12957     eventBus._on("setpreference", evt => preferences.set(evt.name, evt.value), opts);
12958   },
12959   bindWindowEvents() {
12960     if (this._windowAbortController) {
12961       return;
12962     }
12963     this._windowAbortController = new AbortController();
12964     const {
12965       eventBus,
12966       appConfig: {
12967         mainContainer
12968       },
12969       pdfViewer,
12970       _windowAbortController: {
12971         signal
12972       }
12973     } = this;
12974     this._touchManager = new TouchManager({
12975       container: window,
12976       isPinchingDisabled: () => pdfViewer.isInPresentationMode,
12977       isPinchingStopped: () => this.overlayManager?.active,
12978       onPinching: this.touchPinchCallback.bind(this),
12979       onPinchEnd: this.touchPinchEndCallback.bind(this),
12980       signal
12981     });
12982     function addWindowResolutionChange(evt = null) {
12983       if (evt) {
12984         pdfViewer.refresh();
12985       }
12986       const mediaQueryList = window.matchMedia(`(resolution: ${window.devicePixelRatio || 1}dppx)`);
12987       mediaQueryList.addEventListener("change", addWindowResolutionChange, {
12988         once: true,
12989         signal
12990       });
12991     }
12992     addWindowResolutionChange();
12993     window.addEventListener("wheel", onWheel.bind(this), {
12994       passive: false,
12995       signal
12996     });
12997     window.addEventListener("click", onClick.bind(this), {
12998       signal
12999     });
13000     window.addEventListener("keydown", onKeyDown.bind(this), {
13001       signal
13002     });
13003     window.addEventListener("keyup", onKeyUp.bind(this), {
13004       signal
13005     });
13006     window.addEventListener("resize", () => eventBus.dispatch("resize", {
13007       source: window
13008     }), {
13009       signal
13010     });
13011     window.addEventListener("hashchange", () => {
13012       eventBus.dispatch("hashchange", {
13013         source: window,
13014         hash: document.location.hash.substring(1)
13015       });
13016     }, {
13017       signal
13018     });
13019     window.addEventListener("beforeprint", () => eventBus.dispatch("beforeprint", {
13020       source: window
13021     }), {
13022       signal
13023     });
13024     window.addEventListener("afterprint", () => eventBus.dispatch("afterprint", {
13025       source: window
13026     }), {
13027       signal
13028     });
13029     window.addEventListener("updatefromsandbox", evt => {
13030       eventBus.dispatch("updatefromsandbox", {
13031         source: window,
13032         detail: evt.detail
13033       });
13034     }, {
13035       signal
13036     });
13037     const scrollend = () => {
13038       this._isScrolling = false;
13039       mainContainer.addEventListener("scroll", scroll, {
13040         passive: true,
13041         signal
13042       });
13043       mainContainer.removeEventListener("scrollend", scrollend);
13044       mainContainer.removeEventListener("blur", scrollend);
13045     };
13046     const scroll = () => {
13047       if (this._isCtrlKeyDown) {
13048         return;
13049       }
13050       mainContainer.removeEventListener("scroll", scroll);
13051       this._isScrolling = true;
13052       mainContainer.addEventListener("scrollend", scrollend, {
13053         signal
13054       });
13055       mainContainer.addEventListener("blur", scrollend, {
13056         signal
13057       });
13058     };
13059     mainContainer.addEventListener("scroll", scroll, {
13060       passive: true,
13061       signal
13062     });
13063   },
13064   unbindEvents() {
13065     this._eventBusAbortController?.abort();
13066     this._eventBusAbortController = null;
13067   },
13068   unbindWindowEvents() {
13069     this._windowAbortController?.abort();
13070     this._windowAbortController = null;
13071     this._touchManager = null;
13072   },
13073   async testingClose() {
13074     this.unbindEvents();
13075     this.unbindWindowEvents();
13076     this._globalAbortController?.abort();
13077     this._globalAbortController = null;
13078     this.findBar?.close();
13079     await Promise.all([this.l10n?.destroy(), this.close()]);
13080   },
13081   _accumulateTicks(ticks, prop) {
13082     if (this[prop] > 0 && ticks < 0 || this[prop] < 0 && ticks > 0) {
13083       this[prop] = 0;
13084     }
13085     this[prop] += ticks;
13086     const wholeTicks = Math.trunc(this[prop]);
13087     this[prop] -= wholeTicks;
13088     return wholeTicks;
13089   },
13090   _accumulateFactor(previousScale, factor, prop) {
13091     if (factor === 1) {
13092       return 1;
13093     }
13094     if (this[prop] > 1 && factor < 1 || this[prop] < 1 && factor > 1) {
13095       this[prop] = 1;
13096     }
13097     const newFactor = Math.floor(previousScale * factor * this[prop] * 100) / (100 * previousScale);
13098     this[prop] = factor / newFactor;
13099     return newFactor;
13100   },
13101   _unblockDocumentLoadEvent() {
13102     document.blockUnblockOnload?.(false);
13103     this._unblockDocumentLoadEvent = () => {};
13104   },
13105   get scriptingReady() {
13106     return this.pdfScriptingManager.ready;
13107   }
13109 initCom(PDFViewerApplication);
13110 function onPageRender({
13111   pageNumber
13112 }) {
13113   if (pageNumber === this.page) {
13114     this.toolbar?.updateLoadingIndicatorState(true);
13115   }
13117 function onPageRendered({
13118   pageNumber,
13119   error
13120 }) {
13121   if (pageNumber === this.page) {
13122     this.toolbar?.updateLoadingIndicatorState(false);
13123   }
13124   if (this.pdfSidebar?.visibleView === SidebarView.THUMBS) {
13125     const pageView = this.pdfViewer.getPageView(pageNumber - 1);
13126     const thumbnailView = this.pdfThumbnailViewer?.getThumbnail(pageNumber - 1);
13127     if (pageView) {
13128       thumbnailView?.setImage(pageView);
13129     }
13130   }
13131   if (error) {
13132     this._otherError("pdfjs-rendering-error", error);
13133   }
13135 function onPageMode({
13136   mode
13137 }) {
13138   let view;
13139   switch (mode) {
13140     case "thumbs":
13141       view = SidebarView.THUMBS;
13142       break;
13143     case "bookmarks":
13144     case "outline":
13145       view = SidebarView.OUTLINE;
13146       break;
13147     case "attachments":
13148       view = SidebarView.ATTACHMENTS;
13149       break;
13150     case "layers":
13151       view = SidebarView.LAYERS;
13152       break;
13153     case "none":
13154       view = SidebarView.NONE;
13155       break;
13156     default:
13157       console.error('Invalid "pagemode" hash parameter: ' + mode);
13158       return;
13159   }
13160   this.pdfSidebar?.switchView(view, true);
13162 function onNamedAction(evt) {
13163   switch (evt.action) {
13164     case "GoToPage":
13165       this.appConfig.toolbar?.pageNumber.select();
13166       break;
13167     case "Find":
13168       if (!this.supportsIntegratedFind) {
13169         this.findBar?.toggle();
13170       }
13171       break;
13172     case "Print":
13173       this.triggerPrinting();
13174       break;
13175     case "SaveAs":
13176       this.downloadOrSave();
13177       break;
13178   }
13180 function onSidebarViewChanged({
13181   view
13182 }) {
13183   this.pdfRenderingQueue.isThumbnailViewEnabled = view === SidebarView.THUMBS;
13184   if (this.isInitialViewSet) {
13185     this.store?.set("sidebarView", view).catch(() => {});
13186   }
13188 function onUpdateViewarea({
13189   location
13190 }) {
13191   if (this.isInitialViewSet) {
13192     this.store?.setMultiple({
13193       page: location.pageNumber,
13194       zoom: location.scale,
13195       scrollLeft: location.left,
13196       scrollTop: location.top,
13197       rotation: location.rotation
13198     }).catch(() => {});
13199   }
13200   if (this.appConfig.secondaryToolbar) {
13201     this.appConfig.secondaryToolbar.viewBookmarkButton.href = this.pdfLinkService.getAnchorUrl(location.pdfOpenParams);
13202   }
13204 function onViewerModesChanged(name, evt) {
13205   if (this.isInitialViewSet && !this.pdfViewer.isInPresentationMode) {
13206     this.store?.set(name, evt.mode).catch(() => {});
13207   }
13209 function onResize() {
13210   const {
13211     pdfDocument,
13212     pdfViewer,
13213     pdfRenderingQueue
13214   } = this;
13215   if (pdfRenderingQueue.printing && window.matchMedia("print").matches) {
13216     return;
13217   }
13218   if (!pdfDocument) {
13219     return;
13220   }
13221   const currentScaleValue = pdfViewer.currentScaleValue;
13222   if (currentScaleValue === "auto" || currentScaleValue === "page-fit" || currentScaleValue === "page-width") {
13223     pdfViewer.currentScaleValue = currentScaleValue;
13224   }
13225   pdfViewer.update();
13227 function onHashchange(evt) {
13228   const hash = evt.hash;
13229   if (!hash) {
13230     return;
13231   }
13232   if (!this.isInitialViewSet) {
13233     this.initialBookmark = hash;
13234   } else if (!this.pdfHistory?.popStateInProgress) {
13235     this.pdfLinkService.setHash(hash);
13236   }
13238 function onPageNumberChanged(evt) {
13239   const {
13240     pdfViewer
13241   } = this;
13242   if (evt.value !== "") {
13243     this.pdfLinkService.goToPage(evt.value);
13244   }
13245   if (evt.value !== pdfViewer.currentPageNumber.toString() && evt.value !== pdfViewer.currentPageLabel) {
13246     this.toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
13247   }
13249 function onImageAltTextSettings() {
13250   this.imageAltTextSettings?.open({
13251     enableGuessAltText: AppOptions.get("enableGuessAltText"),
13252     enableNewAltTextWhenAddingImage: AppOptions.get("enableNewAltTextWhenAddingImage")
13253   });
13255 function onFindFromUrlHash(evt) {
13256   this.eventBus.dispatch("find", {
13257     source: evt.source,
13258     type: "",
13259     query: evt.query,
13260     caseSensitive: false,
13261     entireWord: false,
13262     highlightAll: true,
13263     findPrevious: false,
13264     matchDiacritics: true
13265   });
13267 function onUpdateFindMatchesCount({
13268   matchesCount
13269 }) {
13270   if (this.supportsIntegratedFind) {
13271     this.externalServices.updateFindMatchesCount(matchesCount);
13272   } else {
13273     this.findBar?.updateResultsCount(matchesCount);
13274   }
13276 function onUpdateFindControlState({
13277   state,
13278   previous,
13279   entireWord,
13280   matchesCount,
13281   rawQuery
13282 }) {
13283   if (this.supportsIntegratedFind) {
13284     this.externalServices.updateFindControlState({
13285       result: state,
13286       findPrevious: previous,
13287       entireWord,
13288       matchesCount,
13289       rawQuery
13290     });
13291   } else {
13292     this.findBar?.updateUIState(state, previous, matchesCount);
13293   }
13295 function onScaleChanging(evt) {
13296   this.toolbar?.setPageScale(evt.presetValue, evt.scale);
13297   this.pdfViewer.update();
13299 function onRotationChanging(evt) {
13300   if (this.pdfThumbnailViewer) {
13301     this.pdfThumbnailViewer.pagesRotation = evt.pagesRotation;
13302   }
13303   this.forceRendering();
13304   this.pdfViewer.currentPageNumber = evt.pageNumber;
13306 function onPageChanging({
13307   pageNumber,
13308   pageLabel
13309 }) {
13310   this.toolbar?.setPageNumber(pageNumber, pageLabel);
13311   this.secondaryToolbar?.setPageNumber(pageNumber);
13312   if (this.pdfSidebar?.visibleView === SidebarView.THUMBS) {
13313     this.pdfThumbnailViewer?.scrollThumbnailIntoView(pageNumber);
13314   }
13315   const currentPage = this.pdfViewer.getPageView(pageNumber - 1);
13316   this.toolbar?.updateLoadingIndicatorState(currentPage?.renderingState === RenderingStates.RUNNING);
13318 function onWheel(evt) {
13319   const {
13320     pdfViewer,
13321     supportsMouseWheelZoomCtrlKey,
13322     supportsMouseWheelZoomMetaKey,
13323     supportsPinchToZoom
13324   } = this;
13325   if (pdfViewer.isInPresentationMode) {
13326     return;
13327   }
13328   const deltaMode = evt.deltaMode;
13329   let scaleFactor = Math.exp(-evt.deltaY / 100);
13330   const isBuiltInMac = FeatureTest.platform.isMac;
13331   const isPinchToZoom = evt.ctrlKey && !this._isCtrlKeyDown && deltaMode === WheelEvent.DOM_DELTA_PIXEL && evt.deltaX === 0 && (Math.abs(scaleFactor - 1) < 0.05 || isBuiltInMac) && evt.deltaZ === 0;
13332   const origin = [evt.clientX, evt.clientY];
13333   if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) {
13334     evt.preventDefault();
13335     if (this._isScrolling || document.visibilityState === "hidden" || this.overlayManager.active) {
13336       return;
13337     }
13338     if (isPinchToZoom && supportsPinchToZoom) {
13339       scaleFactor = this._accumulateFactor(pdfViewer.currentScale, scaleFactor, "_wheelUnusedFactor");
13340       this.updateZoom(null, scaleFactor, origin);
13341     } else {
13342       const delta = normalizeWheelEventDirection(evt);
13343       let ticks = 0;
13344       if (deltaMode === WheelEvent.DOM_DELTA_LINE || deltaMode === WheelEvent.DOM_DELTA_PAGE) {
13345         ticks = Math.abs(delta) >= 1 ? Math.sign(delta) : this._accumulateTicks(delta, "_wheelUnusedTicks");
13346       } else {
13347         const PIXELS_PER_LINE_SCALE = 30;
13348         ticks = this._accumulateTicks(delta / PIXELS_PER_LINE_SCALE, "_wheelUnusedTicks");
13349       }
13350       this.updateZoom(ticks, null, origin);
13351     }
13352   }
13354 function closeSecondaryToolbar(evt) {
13355   if (!this.secondaryToolbar?.isOpen) {
13356     return;
13357   }
13358   const appConfig = this.appConfig;
13359   if (this.pdfViewer.containsElement(evt.target) || appConfig.toolbar?.container.contains(evt.target) && !appConfig.secondaryToolbar?.toggleButton.contains(evt.target)) {
13360     this.secondaryToolbar.close();
13361   }
13363 function closeEditorUndoBar(evt) {
13364   if (!this.editorUndoBar?.isOpen) {
13365     return;
13366   }
13367   if (this.appConfig.secondaryToolbar?.toolbar.contains(evt.target)) {
13368     this.editorUndoBar.hide();
13369   }
13371 function onClick(evt) {
13372   closeSecondaryToolbar.call(this, evt);
13373   closeEditorUndoBar.call(this, evt);
13375 function onKeyUp(evt) {
13376   if (evt.key === "Control") {
13377     this._isCtrlKeyDown = false;
13378   }
13380 function onKeyDown(evt) {
13381   this._isCtrlKeyDown = evt.key === "Control";
13382   if (this.editorUndoBar?.isOpen && evt.keyCode !== 9 && evt.keyCode !== 16 && !((evt.keyCode === 13 || evt.keyCode === 32) && getActiveOrFocusedElement() === this.appConfig.editorUndoBar.undoButton)) {
13383     this.editorUndoBar.hide();
13384   }
13385   if (this.overlayManager.active) {
13386     return;
13387   }
13388   const {
13389     eventBus,
13390     pdfViewer
13391   } = this;
13392   const isViewerInPresentationMode = pdfViewer.isInPresentationMode;
13393   let handled = false,
13394     ensureViewerFocused = false;
13395   const cmd = (evt.ctrlKey ? 1 : 0) | (evt.altKey ? 2 : 0) | (evt.shiftKey ? 4 : 0) | (evt.metaKey ? 8 : 0);
13396   if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {
13397     switch (evt.keyCode) {
13398       case 70:
13399         if (!this.supportsIntegratedFind && !evt.shiftKey) {
13400           this.findBar?.open();
13401           handled = true;
13402         }
13403         break;
13404       case 71:
13405         if (!this.supportsIntegratedFind) {
13406           const {
13407             state
13408           } = this.findController;
13409           if (state) {
13410             const newState = {
13411               source: window,
13412               type: "again",
13413               findPrevious: cmd === 5 || cmd === 12
13414             };
13415             eventBus.dispatch("find", {
13416               ...state,
13417               ...newState
13418             });
13419           }
13420           handled = true;
13421         }
13422         break;
13423       case 61:
13424       case 107:
13425       case 187:
13426       case 171:
13427         this.zoomIn();
13428         handled = true;
13429         break;
13430       case 173:
13431       case 109:
13432       case 189:
13433         this.zoomOut();
13434         handled = true;
13435         break;
13436       case 48:
13437       case 96:
13438         if (!isViewerInPresentationMode) {
13439           setTimeout(() => {
13440             this.zoomReset();
13441           });
13442           handled = false;
13443         }
13444         break;
13445       case 38:
13446         if (isViewerInPresentationMode || this.page > 1) {
13447           this.page = 1;
13448           handled = true;
13449           ensureViewerFocused = true;
13450         }
13451         break;
13452       case 40:
13453         if (isViewerInPresentationMode || this.page < this.pagesCount) {
13454           this.page = this.pagesCount;
13455           handled = true;
13456           ensureViewerFocused = true;
13457         }
13458         break;
13459     }
13460   }
13461   if (cmd === 3 || cmd === 10) {
13462     switch (evt.keyCode) {
13463       case 80:
13464         this.requestPresentationMode();
13465         handled = true;
13466         this.externalServices.reportTelemetry({
13467           type: "buttons",
13468           data: {
13469             id: "presentationModeKeyboard"
13470           }
13471         });
13472         break;
13473       case 71:
13474         if (this.appConfig.toolbar) {
13475           this.appConfig.toolbar.pageNumber.select();
13476           handled = true;
13477         }
13478         break;
13479     }
13480   }
13481   if (handled) {
13482     if (ensureViewerFocused && !isViewerInPresentationMode) {
13483       pdfViewer.focus();
13484     }
13485     evt.preventDefault();
13486     return;
13487   }
13488   const curElement = getActiveOrFocusedElement();
13489   const curElementTagName = curElement?.tagName.toUpperCase();
13490   if (curElementTagName === "INPUT" || curElementTagName === "TEXTAREA" || curElementTagName === "SELECT" || curElementTagName === "BUTTON" && (evt.keyCode === 13 || evt.keyCode === 32) || curElement?.isContentEditable) {
13491     if (evt.keyCode !== 27) {
13492       return;
13493     }
13494   }
13495   if (cmd === 0) {
13496     let turnPage = 0,
13497       turnOnlyIfPageFit = false;
13498     switch (evt.keyCode) {
13499       case 38:
13500         if (this.supportsCaretBrowsingMode) {
13501           this.moveCaret(true, false);
13502           handled = true;
13503           break;
13504         }
13505       case 33:
13506         if (pdfViewer.isVerticalScrollbarEnabled) {
13507           turnOnlyIfPageFit = true;
13508         }
13509         turnPage = -1;
13510         break;
13511       case 8:
13512         if (!isViewerInPresentationMode) {
13513           turnOnlyIfPageFit = true;
13514         }
13515         turnPage = -1;
13516         break;
13517       case 37:
13518         if (this.supportsCaretBrowsingMode) {
13519           return;
13520         }
13521         if (pdfViewer.isHorizontalScrollbarEnabled) {
13522           turnOnlyIfPageFit = true;
13523         }
13524       case 75:
13525       case 80:
13526         turnPage = -1;
13527         break;
13528       case 27:
13529         if (this.secondaryToolbar?.isOpen) {
13530           this.secondaryToolbar.close();
13531           handled = true;
13532         }
13533         if (!this.supportsIntegratedFind && this.findBar?.opened) {
13534           this.findBar.close();
13535           handled = true;
13536         }
13537         break;
13538       case 40:
13539         if (this.supportsCaretBrowsingMode) {
13540           this.moveCaret(false, false);
13541           handled = true;
13542           break;
13543         }
13544       case 34:
13545         if (pdfViewer.isVerticalScrollbarEnabled) {
13546           turnOnlyIfPageFit = true;
13547         }
13548         turnPage = 1;
13549         break;
13550       case 13:
13551       case 32:
13552         if (!isViewerInPresentationMode) {
13553           turnOnlyIfPageFit = true;
13554         }
13555         turnPage = 1;
13556         break;
13557       case 39:
13558         if (this.supportsCaretBrowsingMode) {
13559           return;
13560         }
13561         if (pdfViewer.isHorizontalScrollbarEnabled) {
13562           turnOnlyIfPageFit = true;
13563         }
13564       case 74:
13565       case 78:
13566         turnPage = 1;
13567         break;
13568       case 36:
13569         if (isViewerInPresentationMode || this.page > 1) {
13570           this.page = 1;
13571           handled = true;
13572           ensureViewerFocused = true;
13573         }
13574         break;
13575       case 35:
13576         if (isViewerInPresentationMode || this.page < this.pagesCount) {
13577           this.page = this.pagesCount;
13578           handled = true;
13579           ensureViewerFocused = true;
13580         }
13581         break;
13582       case 83:
13583         this.pdfCursorTools?.switchTool(CursorTool.SELECT);
13584         break;
13585       case 72:
13586         this.pdfCursorTools?.switchTool(CursorTool.HAND);
13587         break;
13588       case 82:
13589         this.rotatePages(90);
13590         break;
13591       case 115:
13592         this.pdfSidebar?.toggle();
13593         break;
13594     }
13595     if (turnPage !== 0 && (!turnOnlyIfPageFit || pdfViewer.currentScaleValue === "page-fit")) {
13596       if (turnPage > 0) {
13597         pdfViewer.nextPage();
13598       } else {
13599         pdfViewer.previousPage();
13600       }
13601       handled = true;
13602     }
13603   }
13604   if (cmd === 4) {
13605     switch (evt.keyCode) {
13606       case 13:
13607       case 32:
13608         if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== "page-fit") {
13609           break;
13610         }
13611         pdfViewer.previousPage();
13612         handled = true;
13613         break;
13614       case 38:
13615         this.moveCaret(true, true);
13616         handled = true;
13617         break;
13618       case 40:
13619         this.moveCaret(false, true);
13620         handled = true;
13621         break;
13622       case 82:
13623         this.rotatePages(-90);
13624         break;
13625     }
13626   }
13627   if (!handled && !isViewerInPresentationMode) {
13628     if (evt.keyCode >= 33 && evt.keyCode <= 40 || evt.keyCode === 32 && curElementTagName !== "BUTTON") {
13629       ensureViewerFocused = true;
13630     }
13631   }
13632   if (ensureViewerFocused && !pdfViewer.containsElement(curElement)) {
13633     pdfViewer.focus();
13634   }
13635   if (handled) {
13636     evt.preventDefault();
13637   }
13639 function beforeUnload(evt) {
13640   evt.preventDefault();
13641   evt.returnValue = "";
13642   return false;
13645 ;// ./web/viewer.js
13650 const pdfjsVersion = "5.0.71";
13651 const pdfjsBuild = "b48717a99";
13652 const AppConstants = null;
13653 window.PDFViewerApplication = PDFViewerApplication;
13654 window.PDFViewerApplicationConstants = AppConstants;
13655 window.PDFViewerApplicationOptions = AppOptions;
13656 function getViewerConfiguration() {
13657   return {
13658     appContainer: document.body,
13659     principalContainer: document.getElementById("mainContainer"),
13660     mainContainer: document.getElementById("viewerContainer"),
13661     viewerContainer: document.getElementById("viewer"),
13662     toolbar: {
13663       container: document.getElementById("toolbarContainer"),
13664       numPages: document.getElementById("numPages"),
13665       pageNumber: document.getElementById("pageNumber"),
13666       scaleSelect: document.getElementById("scaleSelect"),
13667       customScaleOption: document.getElementById("customScaleOption"),
13668       previous: document.getElementById("previous"),
13669       next: document.getElementById("next"),
13670       zoomIn: document.getElementById("zoomInButton"),
13671       zoomOut: document.getElementById("zoomOutButton"),
13672       print: document.getElementById("printButton"),
13673       editorFreeTextButton: document.getElementById("editorFreeTextButton"),
13674       editorFreeTextParamsToolbar: document.getElementById("editorFreeTextParamsToolbar"),
13675       editorHighlightButton: document.getElementById("editorHighlightButton"),
13676       editorHighlightParamsToolbar: document.getElementById("editorHighlightParamsToolbar"),
13677       editorHighlightColorPicker: document.getElementById("editorHighlightColorPicker"),
13678       editorInkButton: document.getElementById("editorInkButton"),
13679       editorInkParamsToolbar: document.getElementById("editorInkParamsToolbar"),
13680       editorStampButton: document.getElementById("editorStampButton"),
13681       editorStampParamsToolbar: document.getElementById("editorStampParamsToolbar"),
13682       editorSignatureButton: document.getElementById("editorSignatureButton"),
13683       editorSignatureParamsToolbar: document.getElementById("editorSignatureParamsToolbar"),
13684       download: document.getElementById("downloadButton")
13685     },
13686     secondaryToolbar: {
13687       toolbar: document.getElementById("secondaryToolbar"),
13688       toggleButton: document.getElementById("secondaryToolbarToggleButton"),
13689       presentationModeButton: document.getElementById("presentationMode"),
13690       openFileButton: null,
13691       printButton: document.getElementById("secondaryPrint"),
13692       downloadButton: document.getElementById("secondaryDownload"),
13693       viewBookmarkButton: document.getElementById("viewBookmark"),
13694       firstPageButton: document.getElementById("firstPage"),
13695       lastPageButton: document.getElementById("lastPage"),
13696       pageRotateCwButton: document.getElementById("pageRotateCw"),
13697       pageRotateCcwButton: document.getElementById("pageRotateCcw"),
13698       cursorSelectToolButton: document.getElementById("cursorSelectTool"),
13699       cursorHandToolButton: document.getElementById("cursorHandTool"),
13700       scrollPageButton: document.getElementById("scrollPage"),
13701       scrollVerticalButton: document.getElementById("scrollVertical"),
13702       scrollHorizontalButton: document.getElementById("scrollHorizontal"),
13703       scrollWrappedButton: document.getElementById("scrollWrapped"),
13704       spreadNoneButton: document.getElementById("spreadNone"),
13705       spreadOddButton: document.getElementById("spreadOdd"),
13706       spreadEvenButton: document.getElementById("spreadEven"),
13707       imageAltTextSettingsButton: document.getElementById("imageAltTextSettings"),
13708       imageAltTextSettingsSeparator: document.getElementById("imageAltTextSettingsSeparator"),
13709       documentPropertiesButton: document.getElementById("documentProperties")
13710     },
13711     sidebar: {
13712       outerContainer: document.getElementById("outerContainer"),
13713       sidebarContainer: document.getElementById("sidebarContainer"),
13714       toggleButton: document.getElementById("sidebarToggleButton"),
13715       resizer: document.getElementById("sidebarResizer"),
13716       thumbnailButton: document.getElementById("viewThumbnail"),
13717       outlineButton: document.getElementById("viewOutline"),
13718       attachmentsButton: document.getElementById("viewAttachments"),
13719       layersButton: document.getElementById("viewLayers"),
13720       thumbnailView: document.getElementById("thumbnailView"),
13721       outlineView: document.getElementById("outlineView"),
13722       attachmentsView: document.getElementById("attachmentsView"),
13723       layersView: document.getElementById("layersView"),
13724       currentOutlineItemButton: document.getElementById("currentOutlineItem")
13725     },
13726     findBar: {
13727       bar: document.getElementById("findbar"),
13728       toggleButton: document.getElementById("viewFindButton"),
13729       findField: document.getElementById("findInput"),
13730       highlightAllCheckbox: document.getElementById("findHighlightAll"),
13731       caseSensitiveCheckbox: document.getElementById("findMatchCase"),
13732       matchDiacriticsCheckbox: document.getElementById("findMatchDiacritics"),
13733       entireWordCheckbox: document.getElementById("findEntireWord"),
13734       findMsg: document.getElementById("findMsg"),
13735       findResultsCount: document.getElementById("findResultsCount"),
13736       findPreviousButton: document.getElementById("findPreviousButton"),
13737       findNextButton: document.getElementById("findNextButton")
13738     },
13739     passwordOverlay: {
13740       dialog: document.getElementById("passwordDialog"),
13741       label: document.getElementById("passwordText"),
13742       input: document.getElementById("password"),
13743       submitButton: document.getElementById("passwordSubmit"),
13744       cancelButton: document.getElementById("passwordCancel")
13745     },
13746     documentProperties: {
13747       dialog: document.getElementById("documentPropertiesDialog"),
13748       closeButton: document.getElementById("documentPropertiesClose"),
13749       fields: {
13750         fileName: document.getElementById("fileNameField"),
13751         fileSize: document.getElementById("fileSizeField"),
13752         title: document.getElementById("titleField"),
13753         author: document.getElementById("authorField"),
13754         subject: document.getElementById("subjectField"),
13755         keywords: document.getElementById("keywordsField"),
13756         creationDate: document.getElementById("creationDateField"),
13757         modificationDate: document.getElementById("modificationDateField"),
13758         creator: document.getElementById("creatorField"),
13759         producer: document.getElementById("producerField"),
13760         version: document.getElementById("versionField"),
13761         pageCount: document.getElementById("pageCountField"),
13762         pageSize: document.getElementById("pageSizeField"),
13763         linearized: document.getElementById("linearizedField")
13764       }
13765     },
13766     altTextDialog: {
13767       dialog: document.getElementById("altTextDialog"),
13768       optionDescription: document.getElementById("descriptionButton"),
13769       optionDecorative: document.getElementById("decorativeButton"),
13770       textarea: document.getElementById("descriptionTextarea"),
13771       cancelButton: document.getElementById("altTextCancel"),
13772       saveButton: document.getElementById("altTextSave")
13773     },
13774     newAltTextDialog: {
13775       dialog: document.getElementById("newAltTextDialog"),
13776       title: document.getElementById("newAltTextTitle"),
13777       descriptionContainer: document.getElementById("newAltTextDescriptionContainer"),
13778       textarea: document.getElementById("newAltTextDescriptionTextarea"),
13779       disclaimer: document.getElementById("newAltTextDisclaimer"),
13780       learnMore: document.getElementById("newAltTextLearnMore"),
13781       imagePreview: document.getElementById("newAltTextImagePreview"),
13782       createAutomatically: document.getElementById("newAltTextCreateAutomatically"),
13783       createAutomaticallyButton: document.getElementById("newAltTextCreateAutomaticallyButton"),
13784       downloadModel: document.getElementById("newAltTextDownloadModel"),
13785       downloadModelDescription: document.getElementById("newAltTextDownloadModelDescription"),
13786       error: document.getElementById("newAltTextError"),
13787       errorCloseButton: document.getElementById("newAltTextCloseButton"),
13788       cancelButton: document.getElementById("newAltTextCancel"),
13789       notNowButton: document.getElementById("newAltTextNotNow"),
13790       saveButton: document.getElementById("newAltTextSave")
13791     },
13792     altTextSettingsDialog: {
13793       dialog: document.getElementById("altTextSettingsDialog"),
13794       createModelButton: document.getElementById("createModelButton"),
13795       aiModelSettings: document.getElementById("aiModelSettings"),
13796       learnMore: document.getElementById("altTextSettingsLearnMore"),
13797       deleteModelButton: document.getElementById("deleteModelButton"),
13798       downloadModelButton: document.getElementById("downloadModelButton"),
13799       showAltTextDialogButton: document.getElementById("showAltTextDialogButton"),
13800       altTextSettingsCloseButton: document.getElementById("altTextSettingsCloseButton"),
13801       closeButton: document.getElementById("altTextSettingsCloseButton")
13802     },
13803     annotationEditorParams: {
13804       editorFreeTextFontSize: document.getElementById("editorFreeTextFontSize"),
13805       editorFreeTextColor: document.getElementById("editorFreeTextColor"),
13806       editorInkColor: document.getElementById("editorInkColor"),
13807       editorInkThickness: document.getElementById("editorInkThickness"),
13808       editorInkOpacity: document.getElementById("editorInkOpacity"),
13809       editorStampAddImage: document.getElementById("editorStampAddImage"),
13810       editorSignatureAddSignature: document.getElementById("editorSignatureAddSignature"),
13811       editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness"),
13812       editorHighlightShowAll: document.getElementById("editorHighlightShowAll")
13813     },
13814     printContainer: document.getElementById("printContainer"),
13815     editorUndoBar: {
13816       container: document.getElementById("editorUndoBar"),
13817       message: document.getElementById("editorUndoBarMessage"),
13818       undoButton: document.getElementById("editorUndoBarUndoButton"),
13819       closeButton: document.getElementById("editorUndoBarCloseButton")
13820     }
13821   };
13823 function webViewerLoad() {
13824   const config = getViewerConfiguration();
13825   PDFViewerApplication.run(config);
13827 document.blockUnblockOnload?.(true);
13828 if (document.readyState === "interactive" || document.readyState === "complete") {
13829   webViewerLoad();
13830 } else {
13831   document.addEventListener("DOMContentLoaded", webViewerLoad, true);
13834 var __webpack_exports__PDFViewerApplication = __webpack_exports__.PDFViewerApplication;
13835 var __webpack_exports__PDFViewerApplicationConstants = __webpack_exports__.PDFViewerApplicationConstants;
13836 var __webpack_exports__PDFViewerApplicationOptions = __webpack_exports__.PDFViewerApplicationOptions;
13837 export { __webpack_exports__PDFViewerApplication as PDFViewerApplication, __webpack_exports__PDFViewerApplicationConstants as PDFViewerApplicationConstants, __webpack_exports__PDFViewerApplicationOptions as PDFViewerApplicationOptions };