UNPKG

@sync-in/server

Version:

The secure, open-source platform for file storage, sharing, collaboration, and sync

1,882 lines (1,867 loc) 546 kB
/** * @licstart The following is the entire license notice for the * JavaScript code in this page * * Copyright 2024 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @licend The above is the entire license notice for the * JavaScript code in this page */ /** * pdfjsVersion = 5.4.54 * pdfjsBuild = 295fb3ec4 */ ;// ./web/pdfjs.js const { AbortException, AnnotationEditorLayer, AnnotationEditorParamsType, AnnotationEditorType, AnnotationEditorUIManager, AnnotationLayer, AnnotationMode, AnnotationType, build, ColorPicker, createValidAbsoluteUrl, DOMSVGFactory, DrawLayer, FeatureTest, fetchData, getDocument, getFilenameFromUrl, getPdfFilenameFromUrl: pdfjs_getPdfFilenameFromUrl, getRGB, getUuid, getXfaPageViewport, GlobalWorkerOptions, ImageKind, InvalidPDFException, isDataScheme, isPdfFile, isValidExplicitDest, MathClamp, noContextMenu, normalizeUnicode, OPS, OutputScale, PasswordResponses, PDFDataRangeTransport, PDFDateString, PDFWorker, PermissionFlag, PixelsPerInch, RenderingCancelledException, ResponseException, setLayerDimensions, shadow, SignatureExtractor, stopEvent, SupportedImageMimeTypes, TextLayer, TouchManager, updateUrlHash, Util, VerbosityLevel, version, XfaLayer } = globalThis.pdfjsLib; ;// ./web/ui_utils.js const DEFAULT_SCALE_VALUE = "auto"; const DEFAULT_SCALE = 1.0; const DEFAULT_SCALE_DELTA = 1.1; const MIN_SCALE = 0.1; const MAX_SCALE = 10.0; const UNKNOWN_SCALE = 0; const MAX_AUTO_SCALE = 1.25; const SCROLLBAR_PADDING = 40; const VERTICAL_PADDING = 5; const RenderingStates = { INITIAL: 0, RUNNING: 1, PAUSED: 2, FINISHED: 3 }; const PresentationModeState = { UNKNOWN: 0, NORMAL: 1, CHANGING: 2, FULLSCREEN: 3 }; const SidebarView = { UNKNOWN: -1, NONE: 0, THUMBS: 1, OUTLINE: 2, ATTACHMENTS: 3, LAYERS: 4 }; const TextLayerMode = { DISABLE: 0, ENABLE: 1, ENABLE_PERMISSIONS: 2 }; const ScrollMode = { UNKNOWN: -1, VERTICAL: 0, HORIZONTAL: 1, WRAPPED: 2, PAGE: 3 }; const SpreadMode = { UNKNOWN: -1, NONE: 0, ODD: 1, EVEN: 2 }; const CursorTool = { SELECT: 0, HAND: 1, ZOOM: 2 }; const AutoPrintRegExp = /\bprint\s*\(/; function scrollIntoView(element, spot, scrollMatches = false) { let parent = element.offsetParent; if (!parent) { console.error("offsetParent is not set -- cannot scroll"); return; } let offsetY = element.offsetTop + element.clientTop; let offsetX = element.offsetLeft + element.clientLeft; while (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth || scrollMatches && (parent.classList.contains("markedContent") || getComputedStyle(parent).overflow === "hidden")) { offsetY += parent.offsetTop; offsetX += parent.offsetLeft; parent = parent.offsetParent; if (!parent) { return; } } if (spot) { if (spot.top !== undefined) { offsetY += spot.top; } if (spot.left !== undefined) { offsetX += spot.left; parent.scrollLeft = offsetX; } } parent.scrollTop = offsetY; } function watchScroll(viewAreaElement, callback, abortSignal = undefined) { const debounceScroll = function (evt) { if (rAF) { return; } rAF = window.requestAnimationFrame(function viewAreaElementScrolled() { rAF = null; const currentX = viewAreaElement.scrollLeft; const lastX = state.lastX; if (currentX !== lastX) { state.right = currentX > lastX; } state.lastX = currentX; const currentY = viewAreaElement.scrollTop; const lastY = state.lastY; if (currentY !== lastY) { state.down = currentY > lastY; } state.lastY = currentY; callback(state); }); }; const state = { right: true, down: true, lastX: viewAreaElement.scrollLeft, lastY: viewAreaElement.scrollTop, _eventHandler: debounceScroll }; let rAF = null; viewAreaElement.addEventListener("scroll", debounceScroll, { useCapture: true, signal: abortSignal }); abortSignal?.addEventListener("abort", () => window.cancelAnimationFrame(rAF), { once: true }); return state; } function parseQueryString(query) { const params = new Map(); for (const [key, value] of new URLSearchParams(query)) { params.set(key.toLowerCase(), value); } return params; } const InvisibleCharsRegExp = /[\x00-\x1F]/g; function removeNullCharacters(str, replaceInvisible = false) { if (!InvisibleCharsRegExp.test(str)) { return str; } if (replaceInvisible) { return str.replaceAll(InvisibleCharsRegExp, m => m === "\x00" ? "" : " "); } return str.replaceAll("\x00", ""); } function binarySearchFirstItem(items, condition, start = 0) { let minIndex = start; let maxIndex = items.length - 1; if (maxIndex < 0 || !condition(items[maxIndex])) { return items.length; } if (condition(items[minIndex])) { return minIndex; } while (minIndex < maxIndex) { const currentIndex = minIndex + maxIndex >> 1; const currentItem = items[currentIndex]; if (condition(currentItem)) { maxIndex = currentIndex; } else { minIndex = currentIndex + 1; } } return minIndex; } function approximateFraction(x) { if (Math.floor(x) === x) { return [x, 1]; } const xinv = 1 / x; const limit = 8; if (xinv > limit) { return [1, limit]; } else if (Math.floor(xinv) === xinv) { return [1, xinv]; } const x_ = x > 1 ? xinv : x; let a = 0, b = 1, c = 1, d = 1; while (true) { const p = a + c, q = b + d; if (q > limit) { break; } if (x_ <= p / q) { c = p; d = q; } else { a = p; b = q; } } let result; if (x_ - a / b < c / d - x_) { result = x_ === x ? [a, b] : [b, a]; } else { result = x_ === x ? [c, d] : [d, c]; } return result; } function floorToDivide(x, div) { return x - x % div; } function getPageSizeInches({ view, userUnit, rotate }) { const [x1, y1, x2, y2] = view; const changeOrientation = rotate % 180 !== 0; const width = (x2 - x1) / 72 * userUnit; const height = (y2 - y1) / 72 * userUnit; return { width: changeOrientation ? height : width, height: changeOrientation ? width : height }; } function backtrackBeforeAllVisibleElements(index, views, top) { if (index < 2) { return index; } let elt = views[index].div; let pageTop = elt.offsetTop + elt.clientTop; if (pageTop >= top) { elt = views[index - 1].div; pageTop = elt.offsetTop + elt.clientTop; } for (let i = index - 2; i >= 0; --i) { elt = views[i].div; if (elt.offsetTop + elt.clientTop + elt.clientHeight <= pageTop) { break; } index = i; } return index; } function getVisibleElements({ scrollEl, views, sortByVisibility = false, horizontal = false, rtl = false }) { const top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight; const left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth; function isElementBottomAfterViewTop(view) { const element = view.div; const elementBottom = element.offsetTop + element.clientTop + element.clientHeight; return elementBottom > top; } function isElementNextAfterViewHorizontally(view) { const element = view.div; const elementLeft = element.offsetLeft + element.clientLeft; const elementRight = elementLeft + element.clientWidth; return rtl ? elementLeft < right : elementRight > left; } const visible = [], ids = new Set(), numViews = views.length; let firstVisibleElementInd = binarySearchFirstItem(views, horizontal ? isElementNextAfterViewHorizontally : isElementBottomAfterViewTop); if (firstVisibleElementInd > 0 && firstVisibleElementInd < numViews && !horizontal) { firstVisibleElementInd = backtrackBeforeAllVisibleElements(firstVisibleElementInd, views, top); } let lastEdge = horizontal ? right : -1; for (let i = firstVisibleElementInd; i < numViews; i++) { const view = views[i], element = view.div; const currentWidth = element.offsetLeft + element.clientLeft; const currentHeight = element.offsetTop + element.clientTop; const viewWidth = element.clientWidth, viewHeight = element.clientHeight; const viewRight = currentWidth + viewWidth; const viewBottom = currentHeight + viewHeight; if (lastEdge === -1) { if (viewBottom >= bottom) { lastEdge = viewBottom; } } else if ((horizontal ? currentWidth : currentHeight) > lastEdge) { break; } if (viewBottom <= top || currentHeight >= bottom || viewRight <= left || currentWidth >= right) { continue; } const minY = Math.max(0, top - currentHeight); const minX = Math.max(0, left - currentWidth); const hiddenHeight = minY + Math.max(0, viewBottom - bottom); const hiddenWidth = minX + Math.max(0, viewRight - right); const fractionHeight = (viewHeight - hiddenHeight) / viewHeight, fractionWidth = (viewWidth - hiddenWidth) / viewWidth; const percent = fractionHeight * fractionWidth * 100 | 0; visible.push({ id: view.id, x: currentWidth, y: currentHeight, visibleArea: percent === 100 ? null : { minX, minY, maxX: Math.min(viewRight, right) - currentWidth, maxY: Math.min(viewBottom, bottom) - currentHeight }, view, percent, widthPercent: fractionWidth * 100 | 0 }); ids.add(view.id); } const first = visible[0], last = visible.at(-1); if (sortByVisibility) { visible.sort(function (a, b) { const pc = a.percent - b.percent; if (Math.abs(pc) > 0.001) { return -pc; } return a.id - b.id; }); } return { first, last, views: visible, ids }; } function normalizeWheelEventDirection(evt) { let delta = Math.hypot(evt.deltaX, evt.deltaY); const angle = Math.atan2(evt.deltaY, evt.deltaX); if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) { delta = -delta; } return delta; } function normalizeWheelEventDelta(evt) { const deltaMode = evt.deltaMode; let delta = normalizeWheelEventDirection(evt); const MOUSE_PIXELS_PER_LINE = 30; const MOUSE_LINES_PER_PAGE = 30; if (deltaMode === WheelEvent.DOM_DELTA_PIXEL) { delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE; } else if (deltaMode === WheelEvent.DOM_DELTA_LINE) { delta /= MOUSE_LINES_PER_PAGE; } return delta; } function isValidRotation(angle) { return Number.isInteger(angle) && angle % 90 === 0; } function isValidScrollMode(mode) { return Number.isInteger(mode) && Object.values(ScrollMode).includes(mode) && mode !== ScrollMode.UNKNOWN; } function isValidSpreadMode(mode) { return Number.isInteger(mode) && Object.values(SpreadMode).includes(mode) && mode !== SpreadMode.UNKNOWN; } function isPortraitOrientation(size) { return size.width <= size.height; } const animationStarted = new Promise(function (resolve) { window.requestAnimationFrame(resolve); }); const docStyle = document.documentElement.style; class ProgressBar { #classList = null; #disableAutoFetchTimeout = null; #percent = 0; #style = null; #visible = true; constructor(bar) { this.#classList = bar.classList; this.#style = bar.style; } get percent() { return this.#percent; } set percent(val) { this.#percent = MathClamp(val, 0, 100); if (isNaN(val)) { this.#classList.add("indeterminate"); return; } this.#classList.remove("indeterminate"); this.#style.setProperty("--progressBar-percent", `${this.#percent}%`); } setWidth(viewer) { if (!viewer) { return; } const container = viewer.parentNode; const scrollbarWidth = container.offsetWidth - viewer.offsetWidth; if (scrollbarWidth > 0) { this.#style.setProperty("--progressBar-end-offset", `${scrollbarWidth}px`); } } setDisableAutoFetch(delay = 5000) { if (this.#percent === 100 || isNaN(this.#percent)) { return; } if (this.#disableAutoFetchTimeout) { clearTimeout(this.#disableAutoFetchTimeout); } this.show(); this.#disableAutoFetchTimeout = setTimeout(() => { this.#disableAutoFetchTimeout = null; this.hide(); }, delay); } hide() { if (!this.#visible) { return; } this.#visible = false; this.#classList.add("hidden"); } show() { if (this.#visible) { return; } this.#visible = true; this.#classList.remove("hidden"); } } function getActiveOrFocusedElement() { let curRoot = document; let curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus"); while (curActiveOrFocused?.shadowRoot) { curRoot = curActiveOrFocused.shadowRoot; curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus"); } return curActiveOrFocused; } function apiPageLayoutToViewerModes(layout) { let scrollMode = ScrollMode.VERTICAL, spreadMode = SpreadMode.NONE; switch (layout) { case "SinglePage": scrollMode = ScrollMode.PAGE; break; case "OneColumn": break; case "TwoPageLeft": scrollMode = ScrollMode.PAGE; case "TwoColumnLeft": spreadMode = SpreadMode.ODD; break; case "TwoPageRight": scrollMode = ScrollMode.PAGE; case "TwoColumnRight": spreadMode = SpreadMode.EVEN; break; } return { scrollMode, spreadMode }; } function apiPageModeToSidebarView(mode) { switch (mode) { case "UseNone": return SidebarView.NONE; case "UseThumbs": return SidebarView.THUMBS; case "UseOutlines": return SidebarView.OUTLINE; case "UseAttachments": return SidebarView.ATTACHMENTS; case "UseOC": return SidebarView.LAYERS; } return SidebarView.NONE; } function toggleCheckedBtn(button, toggle, view = null) { button.classList.toggle("toggled", toggle); button.setAttribute("aria-checked", toggle); view?.classList.toggle("hidden", !toggle); } function toggleExpandedBtn(button, toggle, view = null) { button.classList.toggle("toggled", toggle); button.setAttribute("aria-expanded", toggle); view?.classList.toggle("hidden", !toggle); } const calcRound = function () { const e = document.createElement("div"); e.style.width = "round(down, calc(1.6666666666666665 * 792px), 1px)"; return e.style.width === "calc(1320px)" ? Math.fround : x => x; }(); ;// ./web/app_options.js { var compatParams = new Map(); const { maxTouchPoints, platform, userAgent } = navigator; const isAndroid = /Android/.test(userAgent); const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent) || platform === "MacIntel" && maxTouchPoints > 1; (function () { if (isIOS || isAndroid) { compatParams.set("maxCanvasPixels", 5242880); } })(); (function () { if (isAndroid) { compatParams.set("useSystemFonts", false); } })(); } const OptionKind = { BROWSER: 0x01, VIEWER: 0x02, API: 0x04, WORKER: 0x08, EVENT_DISPATCH: 0x10, PREFERENCE: 0x80 }; const Type = { BOOLEAN: 0x01, NUMBER: 0x02, OBJECT: 0x04, STRING: 0x08, UNDEFINED: 0x10 }; const defaultOptions = { allowedGlobalEvents: { value: null, kind: OptionKind.BROWSER }, canvasMaxAreaInBytes: { value: -1, kind: OptionKind.BROWSER + OptionKind.API }, isInAutomation: { value: false, kind: OptionKind.BROWSER }, localeProperties: { value: { lang: navigator.language || "en-US" }, kind: OptionKind.BROWSER }, maxCanvasDim: { value: 32767, kind: OptionKind.BROWSER + OptionKind.VIEWER }, nimbusDataStr: { value: "", kind: OptionKind.BROWSER }, supportsCaretBrowsingMode: { value: false, kind: OptionKind.BROWSER }, supportsDocumentFonts: { value: true, kind: OptionKind.BROWSER }, supportsIntegratedFind: { value: false, kind: OptionKind.BROWSER }, supportsMouseWheelZoomCtrlKey: { value: true, kind: OptionKind.BROWSER }, supportsMouseWheelZoomMetaKey: { value: true, kind: OptionKind.BROWSER }, supportsPinchToZoom: { value: true, kind: OptionKind.BROWSER }, supportsPrinting: { value: true, kind: OptionKind.BROWSER }, toolbarDensity: { value: 0, kind: OptionKind.BROWSER + OptionKind.EVENT_DISPATCH }, altTextLearnMoreUrl: { value: "", kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, annotationEditorMode: { value: 0, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, annotationMode: { value: 2, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, capCanvasAreaFactor: { value: 200, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, cursorToolOnLoad: { value: 0, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, debuggerSrc: { value: "./debugger.mjs", kind: OptionKind.VIEWER }, defaultZoomDelay: { value: 400, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, defaultZoomValue: { value: "", kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, disableHistory: { value: false, kind: OptionKind.VIEWER }, disablePageLabels: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enableAltText: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enableAltTextModelDownload: { value: true, kind: OptionKind.VIEWER + OptionKind.PREFERENCE + OptionKind.EVENT_DISPATCH }, enableAutoLinking: { value: true, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enableComment: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enableDetailCanvas: { value: true, kind: OptionKind.VIEWER }, enableGuessAltText: { value: true, kind: OptionKind.VIEWER + OptionKind.PREFERENCE + OptionKind.EVENT_DISPATCH }, enableHighlightFloatingButton: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enableNewAltTextWhenAddingImage: { value: true, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enablePermissions: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enablePrintAutoRotate: { value: true, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enableScripting: { value: true, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enableSignatureEditor: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, enableUpdatedAddImage: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, externalLinkRel: { value: "noopener noreferrer nofollow", kind: OptionKind.VIEWER }, externalLinkTarget: { value: 0, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, highlightEditorColors: { value: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F," + "yellow_HCM=#FFFFCC,green_HCM=#53FFBC,blue_HCM=#80EBFF,pink_HCM=#F6B8FF,red_HCM=#C50043", kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, historyUpdateUrl: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, ignoreDestinationZoom: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, imageResourcesPath: { value: "./images/", kind: OptionKind.VIEWER }, maxCanvasPixels: { value: 2 ** 25, kind: OptionKind.VIEWER }, minDurationToUpdateCanvas: { value: 500, kind: OptionKind.VIEWER }, forcePageColors: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, pageColorsBackground: { value: "Canvas", kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, pageColorsForeground: { value: "CanvasText", kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, pdfBugEnabled: { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, printResolution: { value: 150, kind: OptionKind.VIEWER }, sidebarViewOnLoad: { value: -1, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, scrollModeOnLoad: { value: -1, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, spreadModeOnLoad: { value: -1, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, textLayerMode: { value: 1, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, viewerCssTheme: { value: 0, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, viewOnLoad: { value: 0, kind: OptionKind.VIEWER + OptionKind.PREFERENCE }, cMapPacked: { value: true, kind: OptionKind.API }, cMapUrl: { value: "../web/cmaps/", kind: OptionKind.API }, disableAutoFetch: { value: false, kind: OptionKind.API + OptionKind.PREFERENCE }, disableFontFace: { value: false, kind: OptionKind.API + OptionKind.PREFERENCE }, disableRange: { value: false, kind: OptionKind.API + OptionKind.PREFERENCE }, disableStream: { value: false, kind: OptionKind.API + OptionKind.PREFERENCE }, docBaseUrl: { value: "", kind: OptionKind.API }, enableHWA: { value: true, kind: OptionKind.API + OptionKind.VIEWER + OptionKind.PREFERENCE }, enableXfa: { value: true, kind: OptionKind.API + OptionKind.PREFERENCE }, fontExtraProperties: { value: false, kind: OptionKind.API }, iccUrl: { value: "../web/iccs/", kind: OptionKind.API }, isEvalSupported: { value: true, kind: OptionKind.API }, isOffscreenCanvasSupported: { value: true, kind: OptionKind.API }, maxImageSize: { value: -1, kind: OptionKind.API }, pdfBug: { value: false, kind: OptionKind.API }, standardFontDataUrl: { value: "../web/standard_fonts/", kind: OptionKind.API }, useSystemFonts: { value: undefined, kind: OptionKind.API, type: Type.BOOLEAN + Type.UNDEFINED }, verbosity: { value: 1, kind: OptionKind.API }, wasmUrl: { value: "../web/wasm/", kind: OptionKind.API }, workerPort: { value: null, kind: OptionKind.WORKER }, workerSrc: { value: "../build/pdf.worker.mjs", kind: OptionKind.WORKER } }; { defaultOptions.defaultUrl = { value: "compressed.tracemonkey-pldi-09.pdf", kind: OptionKind.VIEWER }; defaultOptions.sandboxBundleSrc = { value: "../build/pdf.sandbox.mjs", kind: OptionKind.VIEWER }; defaultOptions.enableFakeMLManager = { value: true, kind: OptionKind.VIEWER }; } { defaultOptions.disablePreferences = { value: false, kind: OptionKind.VIEWER }; } class AppOptions { static eventBus; static #opts = new Map(); static { for (const name in defaultOptions) { this.#opts.set(name, defaultOptions[name].value); } for (const [name, value] of compatParams) { this.#opts.set(name, value); } this._hasInvokedSet = false; this._checkDisablePreferences = () => { if (this.get("disablePreferences")) { return true; } if (this._hasInvokedSet) { console.warn("The Preferences may override manually set AppOptions; " + 'please use the "disablePreferences"-option to prevent that.'); } return false; }; } static get(name) { return this.#opts.get(name); } static getAll(kind = null, defaultOnly = false) { const options = Object.create(null); for (const name in defaultOptions) { const defaultOpt = defaultOptions[name]; if (kind && !(kind & defaultOpt.kind)) { continue; } options[name] = !defaultOnly ? this.#opts.get(name) : defaultOpt.value; } return options; } static set(name, value) { this.setAll({ [name]: value }); } static setAll(options, prefs = false) { this._hasInvokedSet ||= true; let events; for (const name in options) { const defaultOpt = defaultOptions[name], userOpt = options[name]; if (!defaultOpt || !(typeof userOpt === typeof defaultOpt.value || Type[(typeof userOpt).toUpperCase()] & defaultOpt.type)) { continue; } const { kind } = defaultOpt; if (prefs && !(kind & OptionKind.BROWSER || kind & OptionKind.PREFERENCE)) { continue; } if (this.eventBus && kind & OptionKind.EVENT_DISPATCH) { (events ||= new Map()).set(name, userOpt); } this.#opts.set(name, userOpt); } if (events) { for (const [name, value] of events) { this.eventBus.dispatch(name.toLowerCase(), { source: this, value }); } } } } ;// ./web/pdf_link_service.js const DEFAULT_LINK_REL = "noopener noreferrer nofollow"; const LinkTarget = { NONE: 0, SELF: 1, BLANK: 2, PARENT: 3, TOP: 4 }; class PDFLinkService { externalLinkEnabled = true; constructor({ eventBus, externalLinkTarget = null, externalLinkRel = null, ignoreDestinationZoom = false } = {}) { this.eventBus = eventBus; this.externalLinkTarget = externalLinkTarget; this.externalLinkRel = externalLinkRel; this._ignoreDestinationZoom = ignoreDestinationZoom; this.baseUrl = null; this.pdfDocument = null; this.pdfViewer = null; this.pdfHistory = null; } setDocument(pdfDocument, baseUrl = null) { this.baseUrl = baseUrl; this.pdfDocument = pdfDocument; } setViewer(pdfViewer) { this.pdfViewer = pdfViewer; } setHistory(pdfHistory) { this.pdfHistory = pdfHistory; } get pagesCount() { return this.pdfDocument ? this.pdfDocument.numPages : 0; } get page() { return this.pdfDocument ? this.pdfViewer.currentPageNumber : 1; } set page(value) { if (this.pdfDocument) { this.pdfViewer.currentPageNumber = value; } } get rotation() { return this.pdfDocument ? this.pdfViewer.pagesRotation : 0; } set rotation(value) { if (this.pdfDocument) { this.pdfViewer.pagesRotation = value; } } get isInPresentationMode() { return this.pdfDocument ? this.pdfViewer.isInPresentationMode : false; } async goToDestination(dest) { if (!this.pdfDocument) { return; } let namedDest, explicitDest, pageNumber; if (typeof dest === "string") { namedDest = dest; explicitDest = await this.pdfDocument.getDestination(dest); } else { namedDest = null; explicitDest = await dest; } if (!Array.isArray(explicitDest)) { console.error(`goToDestination: "${explicitDest}" is not a valid destination array, for dest="${dest}".`); return; } const [destRef] = explicitDest; if (destRef && typeof destRef === "object") { pageNumber = this.pdfDocument.cachedPageNumber(destRef); if (!pageNumber) { try { pageNumber = (await this.pdfDocument.getPageIndex(destRef)) + 1; } catch { console.error(`goToDestination: "${destRef}" is not a valid page reference, for dest="${dest}".`); return; } } } else if (Number.isInteger(destRef)) { pageNumber = destRef + 1; } if (!pageNumber || pageNumber < 1 || pageNumber > this.pagesCount) { console.error(`goToDestination: "${pageNumber}" is not a valid page number, for dest="${dest}".`); return; } if (this.pdfHistory) { this.pdfHistory.pushCurrentPosition(); this.pdfHistory.push({ namedDest, explicitDest, pageNumber }); } this.pdfViewer.scrollPageIntoView({ pageNumber, destArray: explicitDest, ignoreDestinationZoom: this._ignoreDestinationZoom }); const ac = new AbortController(); this.eventBus._on("textlayerrendered", evt => { if (evt.pageNumber === pageNumber) { evt.source.textLayer.div.focus(); ac.abort(); } }, { signal: ac.signal }); } goToPage(val) { if (!this.pdfDocument) { return; } const pageNumber = typeof val === "string" && this.pdfViewer.pageLabelToPageNumber(val) || val | 0; if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.pagesCount)) { console.error(`PDFLinkService.goToPage: "${val}" is not a valid page.`); return; } if (this.pdfHistory) { this.pdfHistory.pushCurrentPosition(); this.pdfHistory.pushPage(pageNumber); } this.pdfViewer.scrollPageIntoView({ pageNumber }); } addLinkAttributes(link, url, newWindow = false) { if (!url || typeof url !== "string") { throw new Error('A valid "url" parameter must provided.'); } const target = newWindow ? LinkTarget.BLANK : this.externalLinkTarget, rel = this.externalLinkRel; if (this.externalLinkEnabled) { link.href = link.title = url; } else { link.href = ""; link.title = `Disabled: ${url}`; link.onclick = () => false; } let targetStr = ""; switch (target) { case LinkTarget.NONE: break; case LinkTarget.SELF: targetStr = "_self"; break; case LinkTarget.BLANK: targetStr = "_blank"; break; case LinkTarget.PARENT: targetStr = "_parent"; break; case LinkTarget.TOP: targetStr = "_top"; break; } link.target = targetStr; link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL; } getDestinationHash(dest) { if (typeof dest === "string") { if (dest.length > 0) { return this.getAnchorUrl("#" + escape(dest)); } } else if (Array.isArray(dest)) { const str = JSON.stringify(dest); if (str.length > 0) { return this.getAnchorUrl("#" + escape(str)); } } return this.getAnchorUrl(""); } getAnchorUrl(anchor) { return this.baseUrl ? this.baseUrl + anchor : anchor; } setHash(hash) { if (!this.pdfDocument) { return; } let pageNumber, dest; if (hash.includes("=")) { const params = parseQueryString(hash); if (params.has("search")) { const query = params.get("search").replaceAll('"', ""), phrase = params.get("phrase") === "true"; this.eventBus.dispatch("findfromurlhash", { source: this, query: phrase ? query : query.match(/\S+/g) }); } if (params.has("page")) { pageNumber = params.get("page") | 0 || 1; } if (params.has("zoom")) { const zoomArgs = params.get("zoom").split(","); const zoomArg = zoomArgs[0]; const zoomArgNumber = parseFloat(zoomArg); if (!zoomArg.includes("Fit")) { dest = [null, { name: "XYZ" }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null, zoomArgs.length > 2 ? zoomArgs[2] | 0 : null, zoomArgNumber ? zoomArgNumber / 100 : zoomArg]; } else if (zoomArg === "Fit" || zoomArg === "FitB") { dest = [null, { name: zoomArg }]; } else if (zoomArg === "FitH" || zoomArg === "FitBH" || zoomArg === "FitV" || zoomArg === "FitBV") { dest = [null, { name: zoomArg }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null]; } else if (zoomArg === "FitR") { if (zoomArgs.length !== 5) { console.error('PDFLinkService.setHash: Not enough parameters for "FitR".'); } else { dest = [null, { name: zoomArg }, zoomArgs[1] | 0, zoomArgs[2] | 0, zoomArgs[3] | 0, zoomArgs[4] | 0]; } } else { console.error(`PDFLinkService.setHash: "${zoomArg}" is not a valid zoom value.`); } } if (dest) { this.pdfViewer.scrollPageIntoView({ pageNumber: pageNumber || this.page, destArray: dest, allowNegativeOffset: true }); } else if (pageNumber) { this.page = pageNumber; } if (params.has("pagemode")) { this.eventBus.dispatch("pagemode", { source: this, mode: params.get("pagemode") }); } if (params.has("nameddest")) { this.goToDestination(params.get("nameddest")); } return; } dest = unescape(hash); try { dest = JSON.parse(dest); if (!Array.isArray(dest)) { dest = dest.toString(); } } catch {} if (typeof dest === "string" || isValidExplicitDest(dest)) { this.goToDestination(dest); return; } console.error(`PDFLinkService.setHash: "${unescape(hash)}" is not a valid destination.`); } executeNamedAction(action) { if (!this.pdfDocument) { return; } switch (action) { case "GoBack": this.pdfHistory?.back(); break; case "GoForward": this.pdfHistory?.forward(); break; case "NextPage": this.pdfViewer.nextPage(); break; case "PrevPage": this.pdfViewer.previousPage(); break; case "LastPage": this.page = this.pagesCount; break; case "FirstPage": this.page = 1; break; default: break; } this.eventBus.dispatch("namedaction", { source: this, action }); } async executeSetOCGState(action) { if (!this.pdfDocument) { return; } const pdfDocument = this.pdfDocument, optionalContentConfig = await this.pdfViewer.optionalContentConfigPromise; if (pdfDocument !== this.pdfDocument) { return; } optionalContentConfig.setOCGState(action); this.pdfViewer.optionalContentConfigPromise = Promise.resolve(optionalContentConfig); } } class SimpleLinkService extends PDFLinkService { setDocument(pdfDocument, baseUrl = null) {} } ;// ./web/event_utils.js const WaitOnType = { EVENT: "event", TIMEOUT: "timeout" }; async function waitOnEventOrTimeout({ target, name, delay = 0 }) { if (typeof target !== "object" || !(name && typeof name === "string") || !(Number.isInteger(delay) && delay >= 0)) { throw new Error("waitOnEventOrTimeout - invalid parameters."); } const { promise, resolve } = Promise.withResolvers(); const ac = new AbortController(); function handler(type) { ac.abort(); clearTimeout(timeout); resolve(type); } const evtMethod = target instanceof EventBus ? "_on" : "addEventListener"; target[evtMethod](name, handler.bind(null, WaitOnType.EVENT), { signal: ac.signal }); const timeout = setTimeout(handler.bind(null, WaitOnType.TIMEOUT), delay); return promise; } class EventBus { #listeners = Object.create(null); on(eventName, listener, options = null) { this._on(eventName, listener, { external: true, once: options?.once, signal: options?.signal }); } off(eventName, listener, options = null) { this._off(eventName, listener); } dispatch(eventName, data) { const eventListeners = this.#listeners[eventName]; if (!eventListeners || eventListeners.length === 0) { return; } let externalListeners; for (const { listener, external, once } of eventListeners.slice(0)) { if (once) { this._off(eventName, listener); } if (external) { (externalListeners ||= []).push(listener); continue; } listener(data); } if (externalListeners) { for (const listener of externalListeners) { listener(data); } externalListeners = null; } } _on(eventName, listener, options = null) { let rmAbort = null; if (options?.signal instanceof AbortSignal) { const { signal } = options; if (signal.aborted) { console.error("Cannot use an `aborted` signal."); return; } const onAbort = () => this._off(eventName, listener); rmAbort = () => signal.removeEventListener("abort", onAbort); signal.addEventListener("abort", onAbort); } const eventListeners = this.#listeners[eventName] ||= []; eventListeners.push({ listener, external: options?.external === true, once: options?.once === true, rmAbort }); } _off(eventName, listener, options = null) { const eventListeners = this.#listeners[eventName]; if (!eventListeners) { return; } for (let i = 0, ii = eventListeners.length; i < ii; i++) { const evt = eventListeners[i]; if (evt.listener === listener) { evt.rmAbort?.(); eventListeners.splice(i, 1); return; } } } } class FirefoxEventBus extends EventBus { #externalServices; #globalEventNames; #isInAutomation; constructor(globalEventNames, externalServices, isInAutomation) { super(); this.#globalEventNames = globalEventNames; this.#externalServices = externalServices; this.#isInAutomation = isInAutomation; } dispatch(eventName, data) { throw new Error("Not implemented: FirefoxEventBus.dispatch"); } } ;// ./web/external_services.js class BaseExternalServices { updateFindControlState(data) {} updateFindMatchesCount(data) {} initPassiveLoading() {} reportTelemetry(data) {} async createL10n() { throw new Error("Not implemented: createL10n"); } createScripting() { throw new Error("Not implemented: createScripting"); } createSignatureStorage() { throw new Error("Not implemented: createSignatureStorage"); } updateEditorStates(data) { throw new Error("Not implemented: updateEditorStates"); } dispatchGlobalEvent(_event) {} } ;// ./web/preferences.js class BasePreferences { #defaults = Object.freeze({ altTextLearnMoreUrl: "", annotationEditorMode: 0, annotationMode: 2, capCanvasAreaFactor: 200, cursorToolOnLoad: 0, defaultZoomDelay: 400, defaultZoomValue: "", disablePageLabels: false, enableAltText: false, enableAltTextModelDownload: true, enableAutoLinking: true, enableComment: false, enableGuessAltText: true, enableHighlightFloatingButton: false, enableNewAltTextWhenAddingImage: true, enablePermissions: false, enablePrintAutoRotate: true, enableScripting: true, enableSignatureEditor: false, enableUpdatedAddImage: false, externalLinkTarget: 0, highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F,yellow_HCM=#FFFFCC,green_HCM=#53FFBC,blue_HCM=#80EBFF,pink_HCM=#F6B8FF,red_HCM=#C50043", historyUpdateUrl: false, ignoreDestinationZoom: false, forcePageColors: false, pageColorsBackground: "Canvas", pageColorsForeground: "CanvasText", pdfBugEnabled: false, sidebarViewOnLoad: -1, scrollModeOnLoad: -1, spreadModeOnLoad: -1, textLayerMode: 1, viewerCssTheme: 0, viewOnLoad: 0, disableAutoFetch: false, disableFontFace: false, disableRange: false, disableStream: false, enableHWA: true, enableXfa: true }); #initializedPromise = null; constructor() { this.#initializedPromise = this._readFromStorage(this.#defaults).then(({ browserPrefs, prefs }) => { if (AppOptions._checkDisablePreferences()) { return; } AppOptions.setAll({ ...browserPrefs, ...prefs }, true); }); } async _writeToStorage(prefObj) { throw new Error("Not implemented: _writeToStorage"); } async _readFromStorage(prefObj) { throw new Error("Not implemented: _readFromStorage"); } async reset() { await this.#initializedPromise; AppOptions.setAll(this.#defaults, true); await this._writeToStorage(this.#defaults); } async set(name, value) { await this.#initializedPromise; AppOptions.setAll({ [name]: value }, true); await this._writeToStorage(AppOptions.getAll(OptionKind.PREFERENCE)); } async get(name) { await this.#initializedPromise; return AppOptions.get(name); } get initializedPromise() { return this.#initializedPromise; } } ;// ./node_modules/@fluent/bundle/esm/types.js class FluentType { constructor(value) { this.value = value; } valueOf() { return this.value; } } class FluentNone extends FluentType { constructor(value = "???") { super(value); } toString(scope) { return `{${this.value}}`; } } class FluentNumber extends FluentType { constructor(value, opts = {}) { super(value); this.opts = opts; } toString(scope) { if (scope) { try { const nf = scope.memoizeIntlObject(Intl.NumberFormat, this.opts); return nf.format(this.value); } catch (err) { scope.reportError(err); } } return this.value.toString(10); } } class FluentDateTime extends FluentType { static supportsValue(value) { if (typeof value === "number") return true; if (value instanceof Date) return true; if (value instanceof FluentType) return FluentDateTime.supportsValue(value.valueOf()); if ("Temporal" in globalThis) { const _Temporal = globalThis.Temporal; if (value instanceof _Temporal.Instant || value instanceof _Temporal.PlainDateTime || value instanceof _Temporal.PlainDate || value instanceof _Temporal.PlainMonthDay || value instanceof _Temporal.PlainTime || value instanceof _Temporal.PlainYearMonth) { return true; } } return false; } constructor(value, opts = {}) { if (value instanceof FluentDateTime) { opts = { ...value.opts, ...opts }; value = value.value; } else if (value instanceof FluentType) { value = value.valueOf(); } if (typeof value === "object" && "calendarId" in value && opts.calendar === undefined) { opts = { ...opts, calendar: value.calendarId }; } super(value); this.opts = opts; } [Symbol.toPrimitive](hint) { return hint === "string" ? this.toString() : this.toNumber(); } toNumber() { const value = this.value; if (typeof value === "number") return value; if (value instanceof Date) return value.getTime(); if ("epochMilliseconds" in value) { return value.epochMilliseconds; } if ("toZonedDateTime" in value) { return value.toZonedDateTime("UTC").epochMilliseconds; } throw new TypeError("Unwrapping a non-number value as a number"); } toString(scope) { if (scope) { try { const dtf = scope.memoizeIntlObject(Intl.DateTimeFormat, this.opts); return dtf.format(this.value); } catch (err) { scope.reportError(err); } } if (typeof this.value === "number" || this.value instanceof Date) { return new Date(this.value).toISOString(); } return this.value.toString(); } } ;// ./node_modules/@fluent/bundle/esm/resolver.js const MAX_PLACEABLES = 100; const FSI = "\u2068"; const PDI = "\u2069"; function match(scope, selector, key) { if (key === selector) { return true; } if (key instanceof FluentNumber && selector instanceof FluentNumber && key.value === selector.value) { return true; } if (selector instanceof FluentNumber && typeof key === "string") { let category = scope.memoizeIntlObject(Intl.PluralRules, selector.opts).select(selector.value); if (key === category) { return true; } } return false; } function getDefault(scope, variants, star) { if (variants[star]) { return resolvePattern(scope, variants[star].value); } scope.reportError(new RangeError("No default")); return new FluentNone(); } function getArguments(scope, args) { const positional = []; const named = Object.create(null); for (const arg of args) { if (arg.type === "narg") { named[arg.name] = resolveExpression(scope, arg.value); } else { positional.push(resolveExpression(scope, arg)); } } return { positional, named }; } function resolveExpression(scope, expr) { switch (expr.type) { case "str": return expr.value; case "num": return new FluentNumber(expr.value, { minimumFractionDigits: expr.precision }); case "var": return resolveVariableReference(scope, expr); case "mesg": return resolveMessageReference(scope, expr); case "term": return resolveTermReference(scope, expr); case "func": return resolveFunctionReference(scope, expr); case "select": return resolveSelectExpression(scope, expr); default: return new FluentNone(); } } function resolveVariableReference(scope, { name }) { let arg; if (scope.params) { if (Object.prototype.hasOwnProperty.call(scope.params, name)) { arg = scope.params[name]; } else { return new FluentNone(`$${name}`); } } else if (scope.args && Object.prototype.hasOwnProperty.call(scope.args, name)) { arg = scope.args[name]; } else { scope.reportError(new ReferenceError(`Unknown variable: $${name}`)); return new FluentNone(`$${name}`); } if (arg instanceof FluentType) { return arg; } switch (typeof arg) { case "string": return arg; case "number": return new FluentNumber(arg); case "object": if (FluentDateTime.supportsValue(arg)) { return new FluentDateTime(arg); } default: scope.reportError(new TypeError(`Variable type not supported: $${name}, ${typeof arg}`)); return new FluentNone(`$${name}`); } } function resolveMessageReference(scope, { name, attr }) { const message = scope.bundle._messages.get(name); if (!message) { scope.reportError(new ReferenceError(`Unknown message: ${name}`)); return new FluentNone(name); } if (attr) { const attribute = message.attributes[attr]; if (attribute) { return resolvePattern(scope, attribute); } scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`)); return new FluentNone(`${name}.${attr}`); } if (message.value) { return resolvePattern(scope, message.value); } scope.reportError(new ReferenceError(`No value: ${name}`)); return new FluentNone(name); } function resolveTermReference(scope, { name, attr, args }) { const id = `-${name}`; const term = scope.bundle._terms.get(id); if (!term) { scope.reportError(new ReferenceError(`Unknown term: ${id}`)); return new FluentNone(id); } if (attr) { const attribute = term.attributes[attr]; if (attribute) { scope.params = getArguments(scope, args).named; const resolved = resolvePattern(scope, attribute); scope.params = null; return resolved; } scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`)); return new FluentNone(`${id}.${attr}`); } scope.params = getArguments(scope, args).named; const resolved = resolvePattern(scope, term.value); scope.params = null; return resolved; } function resolveFunctionReference(scope, { name, args }) { let func = scope.bundle._functions[name]; if (!func) { scope.reportError(new ReferenceError(`Unknown function: ${name}()`)); return new FluentNone(`${name}()`); } if (typeof func !== "function") { scope.reportError(new TypeError(`Function ${name}() is not callable`)); return new FluentNone(`${name}()`); } try { let resolved = getArguments(scope, args); return func(resolved.positional, resolved.named); } catch (err) { scope.reportError(err); return new FluentNone(`${name}()`); } } function resolveSelectExpression(scope, { selector, variants, star }) { let sel = resolveExpression(scope, selector); if (sel instanceof FluentNone) { return getDefault(scope, variants, star); } for (const variant of variants) { const key = resolveExpression(scope, variant.key); if (match(scope, sel, key)) { return resolvePattern(scope, variant.value); } } return getDefault(scope, variants, star); } function resolveComplexPattern(scope, ptn) { if (scope.dirty.has(ptn)) { scope.reportError(new RangeError("Cyclic reference")); return new FluentNone(); } scope.dirty.add(ptn); const result = []; const useIsolating = scope.bundle._useIsolating && ptn.length > 1; for (const elem of ptn) { if (typeof elem === "string") { result.push(scope.bundle._transform(elem)); continue; } scope.placeables++; if (scope.placeables > MAX_PLACEABLES) { scope.dirty.delete(ptn); throw new RangeError(`Too many placeables expanded: ${scope.placeables}, ` + `max allowed is ${MAX_PLACEABLES}`); } if (useIsolating) { result.push(FSI); } result.push(resolveExpression(scope, elem).toString(scope)); if (useIsolating) { result.push(PDI); } } scope.dirty.delete(ptn); return result.join(""); } function resolvePattern(scope, value) { if (typeof value === "string") { return scope.bundle._transform(value); } return resolveComplexPattern(scope, value); } ;// ./node_modules/@fluent/bundle/esm/scope.js class Scope { constructor(bundle, errors, args) { this.dirty = new WeakSet(); this.params = null; this.placeables = 0; this.bundle = bundle; this.errors = errors; this.args = args; } reportError(error) { if (!this.errors || !(error instanceof Error)) { throw error; } this.errors.push(error); } memoizeIntlObject(ctor, opts) { let cache = this.bundle._intls.get(ctor); if (!cache) { cache = {};